>[info] git pull
功能:抓取遠程的新提交(并和本地版本庫合并)。
你的小伙伴已經向`origin/dev`分支推送了他的提交,而碰巧你也對同樣的文件作了修改,并試圖推送:
~~~
$ git add hello.py
$ git commit -m "add coding: utf-8"
[dev bd6ae48] add coding: utf-8
1 file changed, 1 insertion(+)
$ git push origin dev
To git@github.com:michaelliao/learngit.git
! [rejected] dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
~~~
推送失敗,因為你的小伙伴的最新提交和你試圖推送的提交有沖突,解決辦法也很簡單,Git已經提示我們,先用`git pull`把最新的提交從`origin/dev`抓下來,然后,在本地合并,解決沖突,再推送:
~~~
$ git pull
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From github.com:michaelliao/learngit
fc38031..291bea8 dev -> origin/dev
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details
git pull <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream dev origin/<branch>
~~~
`git pull`也失敗了,原因是沒有指定本地`dev`分支與遠程`origin/dev`分支的鏈接,根據提示,設置`dev`和`origin/dev`的鏈接:
~~~
$ git branch --set-upstream dev origin/dev
Branch dev set up to track remote branch dev from origin.
~~~
再`pull`:
~~~
$ git pull
Auto-merging hello.py
CONFLICT (content): Merge conflict in hello.py
Automatic merge failed; fix conflicts and then commit the result.
~~~
這回`git pull`成功,但是合并有沖突,需要手動解決,解決的方法和分支管理中的解決沖突完全一樣。解決后,提交,再`push`:
~~~
$ git commit -m "merge & fix hello.py"
[dev adca45d] merge & fix hello.py
$ git push origin dev
Counting objects: 10, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 747 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)
To git@github.com:michaelliao/learngit.git
291bea8..adca45d dev -> dev
~~~
因此,多人協作的工作模式通常是這樣:
首先,可以試圖用`git push origin branch-name`推送自己的修改;
如果推送失敗,則因為遠程分支比你的本地更新,需要先用`git pull`試圖合并;
如果合并有沖突,則解決沖突,并在本地提交;
沒有沖突或者解決掉沖突后,再用`git push origin branch-name`推送就能成功!
如果`git pull`提示“no tracking information”,則說明本地分支和遠程分支的鏈接關系沒有創建,用命令`git branch --set-upstream branch-name origin/branch-name`。
這就是多人協作的工作模式,一旦熟悉了,就非常簡單。
小結
查看遠程庫信息,使用`git remote -v`;
本地新建的分支如果不推送到遠程,對其他人就是不可見的;
從本地推送分支,使用`git push origin branch-name`,如果推送失敗,先用`git pull`抓取遠程的新提交;
在本地創建和遠程分支對應的分支,使用`git checkout -b branch-name origin/branch-name`,本地和遠程分支的名稱最好一致;
建立本地分支和遠程分支的關聯,使用`git branch --set-upstream branch-name origin/branch-name`;
從遠程抓取分支,使用`git pull`,如果有沖突,要先處理沖突。
擴展知識:
>[info] git pull = git fetch + git merge
但是合并操作并不總是會成功,如果自動合并失敗,會在暫存區對合并前后文件進行標識,工作區進入沖突解決狀態,在沖突解決完成之前不能提交。Git支持多種圖形工具幫助完成沖突解決,執行如下命令,即可自動調用已安裝的沖突解決工具。
注意理解這里的“工作區進入沖突解決狀態”哦。試想一下,如果當前工作現場還在干活貨怎么樣呢?
答:實際上有個合并的操作你也知道了,所以同理,跟合并的情況一樣,如果有“合并”操作,那么進入沖突前必須完成本地工作區未完成的工作,否則就拉失敗了。
實際上不論是合并,還是拉,這與工作區的關系就是,只要發生沖突,就必須要求工作區是干凈的,否則就可以進入“解決沖突狀態”(滿足快速合并的不需要解決沖突)。
實際上,pull只要有本地沒有,遠程有的新提交,哪怕是沒有沖突(當前落后),也會要求本地工作區是干凈的。(因為這會重置工作區,所以要保證你當前進行的工作啊。)
但是如果,這次沒有拉到任何的新提交,則沒有任何事。
注意這里的一個小細節,git的一般任何操作都不需要網絡,也就是如果你不主動獲取遠程版本庫信息的話,在看狀態時,它是不知道遠程領先于本地(遠程有新的提交還沒有拉到本地來),或者本地領先于遠程(本地有新的提交還沒有同步到遠程),但是上面我們pull失敗后明顯看到了遠程領先于本地的信息,我們也知道pull實際是兩步,也就是說雖然pull失敗了,但是fetch這個動作是完成了,只是merge失敗了而已。不信我們撤銷修改(不撤銷修改的話還會報錯和pull一樣),直接merge試下,哈哈,也完成了合并吧。(這些細節都是git的許多小聰明之一。)
上面說得太亂了,其實可以總結下,只要是涉及到會改變工作區的操作,都會檢查工作區是否是干凈的。
注意快速合并(快進式合并)有兩種情況哦,“當前領先”和“當前落后”,前者不會改變工作區,只是移動指針到當前而已,所以不要求工作區是干凈的;而后者會改變工作區,并移動指針到最新的提交,所以會要求工作區是干凈的(沒有為添加到暫存區的修改,暫存區是干凈的)。(注意快速合并沒有一個提交哦,所以有時看不出來是合并過哦)
上面有個地方講錯了,不是所有需要改變工作區都會檢查工作區是否干凈,應該是檢測我們的修改是否與拉取的新的提交是否有沖突。比如拉取得提交里面變動了test文件,但是我們本地只是修改test文件,就不會提示錯誤,不會強制需要我們完成工作。
合并操作也是這樣的哦,很靈活的。也就是說之前都說錯了,不一定要求工作區是干凈的才能合并,只要和新的不產生沖突就不會影響,合并后工作區還可以繼續工作。(或者說只要未完成的工作區文件名單中有本次合并變化/沖突的文件,那么則需要解決當前未完成的工作區問題)
>[info] 總之情況很多,git很復雜,暫時沒有時間去討論所有的情況,我們唯一能做的就是遇到實際情況時根據命令提示去解決問題,現在沒有時間去總結所有的情況。
所有的合并都是兩個提交(對象)的合并。
什么時候需要解決沖突:
兩次提交有共同的文件修改,且內容不同。
總之遇到問題時看提示解決。
### 注意
單純的看這個可能會以為3的父節點是2,實際上3和2的父節點都是1,4是3和2合并的結果。
commits圖

Network圖

* * * * *
Network圖

commit info圖(第一個紅框加載時:Loading branch information……)分支結構信息

還可以看到`dev merge master`提交有兩個父節點。
點擊一個之后,顯示可以和master快速合并。

- 說明
- git配置
- git與github的關系
- 基礎概念
- git命令
- git init
- git status
- git diff
- git log
- git reflog
- git add
- git commit
- git reset
- git checkout
- git rm
- git stash
- git remote
- git push
- git clone
- git branch
- git fetch
- git merge
- git rebase
- git pull
- git tag
- 建立版本庫
- 分支合并
- 遠程庫別名
- Pull requests
- 擴展知識
- 功能文件
- 差異看法
- 注意細節
- github移動端
- git工作系統理解
- 倉庫嵌套問題
- 倉庫的使用問題
- 常用命令
- 學習資料
- 學習總結
- 示例文件
- README.md
- CONTRIBUTING.md
- .gitignore
- coding
- 大小寫問題
- 如何貢獻
- 使用賬號密碼clone
- git目錄分析
- HEAD
- 代碼部署問題
- 開發流程
- 指定公鑰文件