比方首先创建gitserver,顺便clone出两个副本git
mkdir server
cd server git init --bare cd .. git clone server git1 git clone server git2
眼下git branch是空的。bash
咱们提交一点东西创建master分支。服务器
cd git1
touch a.txt git add . git commit -m "init" git push origin master
现在git branch -a 显示:fetch
* master remotes/origin/master
当前系统处于master分支,远程origin的repository上也有一个master分支。两个是tracking的。ui
咱们切到git2如下this
cd ../git2 git pull origin
这时候git2跟git1全然同步了。url
现在咱们開始尝试创建还有一个分支并推送到server。spa
习惯的,咱们仍是切回git1指针
cd ../git1 git checkout -b source
这时候咱们已经有了一个本地分支了,假设这个分支不需要共享,那么你可以一直在这个分支上commit但是不push到server。直到这个分支被合并回主分支或者丢弃。regexp
git branch 显演示样例如如下:
master
* source
咱们终于决定把这个分支push到server上与其它人共享。例如如下:
git push origin source:source
这时候git branch -a 能看到当前repository里面所有的分支,包含两个本地的,两个远程的,本地和远程的都处于tracking状态。
master
* source remotes/origin/master remotes/origin/source
切到还有一个副本。
cd ../git2 git pull origin
显演示样例如如下:
* [新分支] source -> origin/source
git branch -a显示本地已经有了一个远程分支的指针,但是没有tracking这个分支的本地分支:
* master remotes/origin/master remotes/origin/source
相同咱们可以在.git/refs/remotes/origin下看到分支的名字,但是refs/heads如下并无。咱们来检出这个远程分支:
git checkout -b source origin/source
这时候git branch -a 显示就跟git1一致了。git2下也可以编辑source分支并同步。这些都是比較常见的操做,咱们需要注意的是。多分支下默认的參数。比方,在两个分支都改动一点东西:
cd ../git1 git checkout master //modify git add . git commit -m "master modify" git checkout source //modify git add . git commit -m "source modify"
这时候git push origin 是针对当前分支的,因此两个分支同一时候push更新仅仅能
git push origin git checkout master git push origin
pull更新的时候
cd ../git2 git checkout master git pull origin
这会同一时候更新两个分支的指针。但是不会merge还有一个分支,咱们去还有一个分支下
git checkout source git pull origin
但是出错例如如下:
You asked to pull from the remote 'origin', but did not specify a branch. Because this is not the default configured remote for your current branch, you must specify a branch on the command line.
问题在于没有给当前分支配置merge的路径,git不知道去merge哪一个分支。(尽管我认为既然是tracking的不该该不知道啊)。
假设你有 1.6.2 以上版本号的 Git。—track 选项可以同一时候配置merge的路径:
git checkout --track origin/serverfix
这里咱们改动配置文件增长branch “source”:
[core] repositoryformatversion = 0 filemode = false bare = false logallrefupdates = true [remote "origin"] url = /media/cxh/backup/work/ceshi/git/server fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master"这里指server上的refs/heads/master [branch "source"] remote = origin merge = refs/heads/source
这意味着每次fetch origin的时候更新所有remotes/origin的头指针到refs/heads/如下,详细可以去.git下查阅这个文件夹,但是头指针都是仅仅读的。
merge是由所在branch定义的。
咱们加了branch “source”的配置指定当前source的merge策略是使用server端的refs/heads/source来合并到当前分支。
这样就可以顺利的git pull origin了。
咱们先创建新的repo:
cd .. mkdir server2 cd server2 git init --bare
增长git1副本,并提交
git remote add server xxx/server2 git push server
上面过程的本质是提交当前分支头指针到server。至关于拷贝refs/head/xxx到refs/remotes/server/下并提交。
git push server会被展开成
git push server 当前分支名:当前分支名
咱们可以在git2副本相同增长该repository并更新引用
git remote add server xxx/server2 git fetch server
可以看到refs下文件夹结构例如如下:
├── heads │ ├── master │ └── source ├── remotes │ ├── origin │ │ ├── master │ │ └── source │ └── server │ └── source └── tags
update
fetch操做的本质是更新repo所指定远程分支的头指针(server->refs/remotes/xxx/)
merge操做的本质是合并当前分支和指定的头指针(refs/remotes/xxx->refs/heads)
pull操做的本质是fetch + merge
commit
commit的本质是改动了当前分支的头指针(refs/heads)
push操做本质是提交当前分支头指针到server,顺便也改动了本地存储的server头指针(refs/remotes/xxx)
checkout
复制本地分支的本质是拷贝了refs/heads/下的一个头指针
push本地分支到server的本质是把这个头指针上传服务器,顺便拷贝了本地存储的server头指针(refs/remotes/xxx)
tracking远程分支的本质是把refs/remotes/下的指针复制到了refs/heads下
注:以上过程都没有涉及数据流。