1、典型合并
繼續(xù)上面的前一篇文章的示例:
我需要繼續(xù)開發(fā)dev
分支上的功能。
需求:
- 繼續(xù)修改
dev.txt
文件歪玲。 - 修改
readme.txt
文件,因為該文件和master
分支都有的文件掷匠,修改一下為之后創(chuàng)造一個小沖突滥崩。
1)在dev
分支繼續(xù)工作,并提交版本
# 1.查看工作目錄中文件狀態(tài)讹语,非常干凈
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (dev)
$ git status
On branch dev
nothing to commit, working tree clean
# 2.查看版本庫提交歷史
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (dev)
$ git log --oneline --graph --all
* 0690030 (master) 第5次提交钙皮,新增內(nèi)容:branch test v4
| * 9eb3224 (HEAD -> dev) 第4次提交,dev分支開發(fā) dev.txt文件
|/
* b97ccfd 第3次提交,新增內(nèi)容:branch test v3
* f72a9fe 第2次提交短条,新增內(nèi)容:branch test v2
* fa2439a 第1次提交导匣,新增readme.txt文件
# 3.開始修改dev.txt文件和readme.txt文件
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (dev)
$ echo "dev new file v2 100%" >> dev.txt
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (dev)
$ echo "branch test v4 dev 100%" >> readme.txt
# 4.提交到版本庫中
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (dev)
$ git commit -a -m '第6次提交,修改dev和readme文件'
warning: LF will be replaced by CRLF in dev.txt.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in readme.txt.
The file will have its original line endings in your working directory
[dev e94af28] 第6次提交茸时,修改dev和readme文件
2 files changed, 2 insertions(+)
2)查看當前版本庫的歷史提交記錄
# 1.查看歷史提交記錄
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (dev)
$ git log --oneline --graph --all
* e94af28 (HEAD -> dev) 第6次提交贡定,修改dev和readme文件
* 9eb3224 第4次提交,dev分支開發(fā) dev.txt文件
| * 0690030 (master) 第5次提交可都,新增內(nèi)容:branch test v4
|/
* b97ccfd 第3次提交缓待,新增內(nèi)容:branch test v3
* f72a9fe 第2次提交,新增內(nèi)容:branch test v2
* fa2439a 第1次提交汹粤,新增readme.txt文件
此時工作目錄的圖解如下:
3)把dev
分支合并到master
分支上
假設你已經(jīng)開發(fā)完成新需求命斧,并且打算將你的工作合并入 master
分支。
為此嘱兼,你需要合并 dev
分支到 master
分支,這和之前你合并 hotfix
分支的時候贤徒,看起來有一點不一樣芹壕。你會發(fā)現(xiàn)的提交歷史從一個更早的地方開始分叉(diverged:發(fā)散)。
而master
分支所在提交節(jié)點接奈,并不是 dev
分支所在提交點的直接祖先踢涌,所以 Git 不得不做一些額外的工作。
出現(xiàn)這種情況的時候序宦,Git 會使用兩個分支的末端提交的快照(C5
和 C6
)以及這兩個分支的公共祖先(C3
)睁壁,做一個簡單的三方合并。
如下圖:
你只需要切換到你想合并入的分支上互捌,然后運行 git merge
命令:
# 1.查看工作目錄中文件狀態(tài)潘明,非常干凈
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (dev)
$ git status
On branch dev
nothing to commit, working tree clean
# 2.切換到master分支
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (dev)
$ git checkout master
Switched to branch 'master'
但這里要注意,和之前合并 hotfix
分支的不同的是秕噪,指針向前推進所不同钳降。Git 將此次三方合并的結果,做了一個新的快照腌巾,并且自動創(chuàng)建一個新的提交指向它遂填。 這被稱作一次合并提交(典型提交),它的特別之處在于他有不止一個父提交澈蝙。
如下圖所示:
既然你的修改已經(jīng)合并進來了吓坚,就不再需要 dev
分支了, 現(xiàn)在你可以刪除這個分支。
$ git branch -d dev
2灯荧、遇到?jīng)_突時的分支合并
有時候合并操作不會如此順利礁击。 如果你在兩個不同的分支中,對同一個文件的同一個部分進行了不同的修改,Git 就沒法干凈的合并它們客税。
如果你在dev
分支的開發(fā)時况褪,也進行了和 hotfix
分支有關的修改,都涉及到同一個文件的同一處更耻,在合并它們的時候就會產(chǎn)生合并沖突:
接上面練習:
1)合并dev
分支到master
分支上
# 直接合并分支dev到master分支上
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git merge dev
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
說明:
-
Auto-merging readme.txt
:在自動合并readme.txt
文件的過程中测垛, -
CONFLICT (content): Merge conflict in readme.txt
:沖突(內(nèi)容),在readme.txt
文件中發(fā)生沖突秧均。 -
Automatic merge failed; fix conflicts and then commit the result.
:自動合并失敗食侮,你需要手動解決沖突,然后提交結果目胡。
此時 Git 做了合并锯七,但是沒有自動地創(chuàng)建一個新的合并提交。 出現(xiàn)沖突時誉己,Git 會暫停下來眉尸,等待你去解決合并產(chǎn)生的沖突。
你可以在發(fā)生合并沖突后的任意時刻巨双,使用 git status
命令來查看噪猾,那些因包含合并沖突,而處于未合并(unmerged)狀態(tài)的文件筑累。
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master|MERGING)
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Changes to be committed:
new file: dev.txt
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: readme.txt
2)解決readme.txt
文件中的沖突內(nèi)容
在合并分支時袱蜡,產(chǎn)生沖突的文件都會被標識成未合并狀態(tài)(Unmerged),你需要打開這些文件慢宗,手動解決沖突坪蚁。
出現(xiàn)沖突的文件會包含一些特殊區(qū)段,
打開沖突文件readme.txt
如下:
# 編輯readme.txt文件
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master|MERGING)
$ vim readme.txt
# 內(nèi)容如下:
branch test v1
branch test v2
branch test v3
<<<<<<< HEAD
branch test v4
=======
branch test v4 dev 100%
>>>>>>> dev
說明:
-
HEAD
到=======
:表示所在分支的內(nèi)容镜沽,也就是master
分支的內(nèi)容敏晤。 -
=======
到dev
:表示被合并的分支,也就是dev
分支的內(nèi)容
解決沖突方式:
- 你選擇使用由
=======
分割的兩部分中任何的一個淘邻。 - 或者你也可以自行合并這些內(nèi)容茵典。
- 并且
<<<<<<<
,=======
, 和>>>>>>>
這些標識要刪除。
本例修改沖突內(nèi)容如下:
branch test v1
branch test v2
branch test v3
branch test v4 for master
branch test v4 for dev
這樣沖突文件就解決完成了宾舅。
提示: 自己和自己的分支合并時统阿,所產(chǎn)生沖突還好解決,關鍵是自己和同事的分支合并時產(chǎn)生沖突筹我,就比較難解決(基本靠吼扶平,哈哈)。
3)把修改完的沖突文件加入暫存區(qū)并提交
在你解決了所有文件里的沖突之后蔬蕊,對每個文件使用 git add
命令结澄,將其添加到暫存區(qū)中。
一旦暫存這些原本有沖突的文件,Git 就會將它們標記為沖突已解決麻献。
如果你對結果感到滿意们妥,并且確定之前有沖突的的文件都已經(jīng)暫存了,這時你可以輸入 git commit
來完成合并提交勉吻。
# 1.查看工作目錄中文件狀態(tài)
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master|MERGING)
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Changes to be committed:
new file: dev.txt
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: readme.txt
# 2.添加到暫存區(qū)中
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master|MERGING)
$ git add ./
# 3.再次查看工作目錄中文件狀態(tài)
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master|MERGING)
$ git status
On branch master
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
new file: dev.txt
modified: readme.txt
# 4.提交
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master|MERGING)
$ git commit -m '第7次提交监婶,完成dev分支的新功能'
[master 3110083] 第7次提交,完成dev分支的新功能
4)查看版本庫中的提交歷史
# 查看提交歷史
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git log --oneline --graph --all
* 3110083 (HEAD -> master) 第7次提交齿桃,完成dev分支的新功能
|\
| * e94af28 (dev) 第6次提交惑惶,修改dev和readme文件
| * 9eb3224 第4次提交,dev分支開發(fā) dev.txt文件
* | 0690030 第5次提交短纵,新增內(nèi)容:branch test v4
|/
* b97ccfd 第3次提交带污,新增內(nèi)容:branch test v3
* f72a9fe 第2次提交,新增內(nèi)容:branch test v2
* fa2439a 第1次提交香到,新增readme.txt文件
此時dev
分支已經(jīng)完成了自己的使命鱼冀,可以刪除了,留著沒有任何的意義悠就。
# 1.刪除dev分支
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git branch -d dev
Deleted branch dev (was e94af28).
# 2.查看版本庫歷史提交信息
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git log --oneline --graph --all
* 3110083 (HEAD -> master) 第7次提交雷绢,完成dev分支的新功能
|\
| * e94af28 第6次提交,修改dev和readme文件
| * 9eb3224 第4次提交理卑,dev分支開發(fā) dev.txt文件
* | 0690030 第5次提交,新增內(nèi)容:branch test v4
|/
* b97ccfd 第3次提交蔽氨,新增內(nèi)容:branch test v3
* f72a9fe 第2次提交藐唠,新增內(nèi)容:branch test v2
* fa2439a 第1次提交,新增readme.txt文件
# 可以看到信息中鹉究,沒有dev分支的標識了宇立。
此時工作目錄的圖解如下:
如上所示,就是解決一個沖突的全部流程自赔。
3妈嘹、補充:Git與SVN文件沖突對比
Git的沖突檢測單位是文件,即當不同分支對同一個文件進行修改后進行合并绍妨,就會產(chǎn)生沖突润脸。
這是與SVN是不同的。SVN檢測沖突是以文件中的列為單位他去,什么意思毙驯?
- 若兩個分支修改的不是同一個文件,合并時肯定不會產(chǎn)生沖突灾测;
- 但若修改的是同一個文件上的不同行中的內(nèi)容爆价,合并時也不會產(chǎn)生沖突;
- 若修改的是同一個文件上同一行上的不同列,在合并的時候也不會產(chǎn)生沖突铭段;
- 只有兩個分支修改的是同一個文件同一行中同列數(shù)據(jù)的時候骤宣,在合并時才會產(chǎn)生沖突。
Git保存的不是文件的變化或者差異序愚,而是一系列不同時刻的 快照 憔披。