最近同時(shí)同步博客到github和gitcafe上,,遇到一些問(wèn)題,我們分如下幾個(gè)方面來(lái)分析一下:
推送遠(yuǎn)程分支到同一個(gè)服務(wù)器
比如首先建立git服務(wù)器,,順便clone出兩個(gè)副本
mkdir server
cd server
git init --bare
cd ..
git clone server git1
git clone server git2
目前git branch是空的,。我們提交一點(diǎn)東西建立master分支。
cd git1
touch a.txt
git add .
git commit -m "init"
git push origin master
現(xiàn)在git branch -a 顯示:
* master
remotes/origin/master
當(dāng)前系統(tǒng)處于master分支,,遠(yuǎn)程origin的repository上也有一個(gè)master分支,。兩個(gè)是tracking的。我們切到git2下面
cd ../git2
git pull origin
這時(shí)候git2跟git1完全同步了?,F(xiàn)在我們開(kāi)始嘗試建立另一個(gè)分支并推送到服務(wù)器,。習(xí)慣的,我們還是切回git1
cd ../git1
git checkout -b source
這時(shí)候我們已經(jīng)有了一個(gè)本地分支了,,如果這個(gè)分支不需要共享,,那么你可以一直在這個(gè)分支上commit但是不push到服務(wù)器,直到這個(gè)分支被合并回主分支或者丟棄,。git branch 顯示如下:
master
* source
我們最終決定把這個(gè)分支push到服務(wù)器上與其他人共享,,如下:
git push origin source:source
這時(shí)候git branch -a 能看到當(dāng)前repository里面所有的分支,包括兩個(gè)本地的,,兩個(gè)遠(yuǎn)程的,,本地和遠(yuǎn)程的都處于tracking狀態(tài)。
master
* source
remotes/origin/master
remotes/origin/source
切到另一個(gè)副本,。
cd ../git2
git pull origin
顯示如下:
* [新分支] source -> origin/source
git branch -a顯示本地已經(jīng)有了一個(gè)遠(yuǎn)程分支的指針,,但是沒(méi)有tracking這個(gè)分支的本地分支:
* master
remotes/origin/master
remotes/origin/source
同樣我們可以在.git/refs/remotes/origin下看到分支的名字,但是refs/heads下面并沒(méi)有,。我們來(lái)檢出這個(gè)遠(yuǎn)程分支:
git checkout -b source origin/source
這時(shí)候git branch -a 顯示就跟git1一致了,。git2下也可以編輯source分支并同步,。這些都是比較常見(jiàn)的操作,我們需要注意的是,,多分支下默認(rèn)的參數(shù),。比如,在兩個(gè)分支都修改一點(diǎn)東西:
cd ../git1
git checkout master
//modify
git add .
git commit -m "master modify"
git checkout source
//modify
git add .
git commit -m "source modify"
這時(shí)候git push origin 是針對(duì)當(dāng)前分支的,,所以兩個(gè)分支同時(shí)push更新只能
git push origin
git checkout master
git push origin
pull更新的時(shí)候
cd ../git2
git checkout master
git pull origin
這會(huì)同時(shí)更新兩個(gè)分支的指針,,但是不會(huì)merge另一個(gè)分支,我們?nèi)チ硪粋€(gè)分支下
git checkout source
git pull origin
但是出錯(cuò)如下:
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.
問(wèn)題在于沒(méi)有給當(dāng)前分支配置merge的路徑,,git不知道去merge哪個(gè)分支,。(雖然我覺(jué)得既然是tracking的不應(yīng)該不知道啊)。
如果你有 1.6.2 以上版本的 Git,,—track 選項(xiàng)可以同時(shí)配置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的時(shí)候更新所有remotes/origin的頭指針到refs/heads/下面,,具體可以去.git下查閱這個(gè)目錄,但是頭指針都是只讀的,。merge是由所在branch定義的,。
我們加了branch “source”的配置指定當(dāng)前source的merge策略是使用服務(wù)器端的refs/heads/source來(lái)合并到當(dāng)前分支。這樣就可以順利的git pull origin了,。
推送遠(yuǎn)程分支到不同服務(wù)器
我們先建立新的repo:
cd ..
mkdir server2
cd server2
git init --bare
加入git1副本,,并提交
git remote add server xxx/server2
git push server
上面過(guò)程的本質(zhì)是提交當(dāng)前分支頭指針到server,相當(dāng)于拷貝refs/head/xxx到refs/remotes/server/下并提交,。git push server會(huì)被展開(kāi)成
git push server 當(dāng)前分支名:當(dāng)前分支名
我們可以在git2副本同樣加入該repository并更新引用
git remote add server xxx/server2
git fetch server
可以看到refs下目錄結(jié)構(gòu)如下:
├── heads
│ ├── master
│ └── source
├── remotes
│ ├── origin
│ │ ├── master
│ │ └── source
│ └── server
│ └── source
└── tags
總結(jié)一下
-
update
-
fetch操作的本質(zhì)是更新repo所指定遠(yuǎn)程分支的頭指針(server->refs/remotes/xxx/)
-
merge操作的本質(zhì)是合并當(dāng)前分支和指定的頭指針(refs/remotes/xxx->refs/heads)
-
pull操作的本質(zhì)是fetch + merge
-
commit
-
commit的本質(zhì)是修改了當(dāng)前分支的頭指針(refs/heads)
-
push操作本質(zhì)是提交當(dāng)前分支頭指針到server,,順便也修改了本地存儲(chǔ)的server頭指針(refs/remotes/xxx)
-
checkout
-
復(fù)制本地分支的本質(zhì)是拷貝了refs/heads/下的一個(gè)頭指針
-
push本地分支到server的本質(zhì)是把這個(gè)頭指針上傳服務(wù)器,順便拷貝了本地存儲(chǔ)的server頭指針(refs/remotes/xxx)
-
tracking遠(yuǎn)程分支的本質(zhì)是把refs/remotes/下的指針拷貝到了refs/heads下
注:以上過(guò)程都沒(méi)有涉及數(shù)據(jù)流,。
參考文獻(xiàn):
[1] Git 分支 – 遠(yuǎn)程分支, http:///book/zh/Git-%E5%88%86%E6%94%AF-%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF
[2] The Configuration File – “Branch” Section, http://www./topics/the-configuration-file-branch-section/
|