比方首先創建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下
注:以上過程都沒有涉及數據流。