一、rebase
應(yīng)用場景:合并分支,讓日志顯示更加人性化,方便回滾
一般我們合并分支溯香,會使用merge命令,merge命令的原理如下,會在提交的分支后面再增加一個合并分支:
而如果我們使用rebase命令浓恶,會把公共分支放在當(dāng)前分支之前玫坛。
rebase相對于merge的好處是日志更加清晰了,便于回滾包晰。而壞處在于更容易引起沖突湿镀。
接下來我們做一個栗子,來說明一下情況伐憾。 我們新建一個分支master3勉痴,然后新建一個"readme.md"文件,寫入一行內(nèi)容树肃,并且提交到資源庫蒸矛。
git checkout -b master3
echo readme > readme.md
git commit -am "init data"
使用更新日志如下:
接下來我們創(chuàng)建兩個分支,分別取名 "merge-test"和"rebase-test"
git branch merge-test
git branch rebase-test
在master3分支新增三個提交"11","22","33"胸嘴,日志信息與修改的信息相同莉钙。
echo '11' >> readme.md
git commit -am "11"
echo '22' >> readme.md
git commit -am "22"
echo '33' >> readme.md
git commit -am "33"
master3分支的日志如下:
readme.md文件內(nèi)容如下:
現(xiàn)在我們切換到merge-test分支,和master3上做類似的操作筛谚,新增三個提交"aa","bb","cc", 日志信息與修改的信息相同磁玉。 然后合并到 rebase-test 分支。
git checkout merge-test
echo 'aa' >> readme.md
git commit -am "aa"
echo 'bb' >> readme.md
git commit -am "bb"
echo 'cc' >> readme.md
git commit -am "cc"
git checkout rebase-test
git merge/rebase merge-test
merge-test和rebase-test分支日志如下:
readme.md文件內(nèi)容如下:
ps:當(dāng)被合并分支(rebase-test)未做修改驾讲,則rebase和merge分支產(chǎn)生的日志一樣蚊伞。
現(xiàn)在準(zhǔn)備工作已經(jīng)做好了席赂,現(xiàn)在我們分別用merge和rebase的方式把master3分支合并到merge-test和rebase-test中。
merge的栗子
先看merge合并, 會產(chǎn)生沖突时迫。
git checkout merge-test
git merge master3
我們解決一下沖突颅停,并查看一下日志:
git commit -am "merge"
git log --oneline --graph
我們發(fā)現(xiàn)這個日志文件分叉了,現(xiàn)在我們試著回滾到 "bb", 看會發(fā)生什么掠拳。
git reset --hard a01f4c27b2
git log --oneline --graph
日志文件如下:
readme.md文件如下:
我們發(fā)現(xiàn)之前從master3分支合并的代碼沒有了癞揉,需要再合并一次。如果合并的分支越多溺欧,情況很復(fù)雜喊熟,可能就比較難找到到底需要回滾到哪個分支了
rebase的栗子
現(xiàn)在我們來研究一下"rebase"。一樣切換到rebase-test分支, 使用rebase 合并 master3分支姐刁。
git checkout rebase-test
git rebase master3
有沖突,我們發(fā)現(xiàn)是“aa”的提交與 master3上的提交相互比較
我們選擇接受全部芥牌,并且把"aa" 放在 "11" 之前, 調(diào)整成如下樣子:
然后我們解決一下沖突聂使。
git add .
git rebase --continue
然后因為我們修改完的代碼和 "bb"壁拉、"cc"比較都有沖突,按照上面的方式繼續(xù)解決沖突柏靶,然后提交并繼續(xù)git rebase --continue弃理。最終解決好了之后,我們查看一下日志:
我們發(fā)現(xiàn)日志并沒有分叉∈候眩現(xiàn)在我們試著回退到 "bb"
git reset --hard 10755375f1
我們發(fā)現(xiàn)master3分支上的內(nèi)容依然保留著痘昌。
小結(jié)
1、rebase 和 merge 都可以用來合并分支
2.1)當(dāng)被合并分支沒有修改時梆靖,rebase和merge效果一樣
2.2)如果兩個分支都有修改,使用merge會在被合并分支后面增加一次提交笔诵, 沖突也只需要解決1次返吻,但日志分叉,不對回滾不友好乎婿。
2.3)如果兩個分支都有修改测僵,使用rebase在把合并分支與被合并分支的提交逐個合并, 沖突有可能需要解決多次谢翎,但日志無分叉捍靠,對回滾友好。
2森逮、rebase 和 merge如何區(qū)分使用
2.1) 上游分支往下游分支更新代碼時使用 "rebase" (master 往 dev合并時)
2.2) 下游往上游更新代碼時使用 "merge" (dev 往 master 合并時)
3榨婆、使用git pull 默認使用merge方式,如果需要使用 rebase 方式褒侧,使用命令 " git pull --rebase"
二良风、cherry-pick
此命令英譯過來是挑櫻桃的意思谊迄,就是在一些櫻桃里面,挑選出好的櫻桃烟央。在git中统诺,就是把A分支中一些需要的提交挑選出來合并到B分支上面。
我們先來用一個栗子疑俭,來看一下這個命令是怎么用的粮呢。
1、基本用法
我們還是用上一個節(jié)提到的master3分支钞艇,先新建兩個分支 cp-master 和 cp-dev, 然后修改cp-dev啄寡,再把cp-dev中的某些修改合并到cp-master上。
git branch cp-master
git checkout -b cp-dev
然后新增三個次提交
1) 最后一行新增 “xyz”
2) 把 "xyz" 改成 "xyzo"
3) 第二行新增 "789"
echo xyz >> readme.md
git add .
git commit -m "xyz"
vi readme.md
## edit start ##
readme
11
22
33
xyzo
## edit end ##
git commit -am "xyz to xyzo"
## edit start ##
readme
789
11
22
33
xaz
## edit end ##
git commit -am "789"
最終的日志為如下
最終的文件內(nèi)容如下:
接下來我們切換到 "cp-master"分支香璃。
1)把第三次提交(789)更新到cp-master上
git checkout cp-master
git cherry-pick 6538e91943
git log --oneline --graph
2)把第二次提交更新到cp-master上
git cherry-pick 22140132aa
我們發(fā)現(xiàn)有沖突
解決一下沖突
git add .
git cherry-pick --continue
git log --oneline --graph
最后的文件如下:
我們對比發(fā)現(xiàn)兩個分支的最后的文件基本相同这难,但是提交歷史完全不一樣。
2葡秒、Cherry pick 支持一次轉(zhuǎn)移多個提交姻乓。
git cherry-pick <HashA> <HashB>
上面的命令將 A 和 B 兩個提交應(yīng)用到當(dāng)前分支。這會在當(dāng)前分支生成兩個對應(yīng)的新提交眯牧。
如果想要轉(zhuǎn)移一系列的連續(xù)提交蹋岩,可以使用下面的簡便語法。
git cherry-pick A..B
上面的命令可以轉(zhuǎn)移從 A 到 B 的所有提交学少。它們必須按照正確的順序放置:提交 A 必須早于提交 B剪个,否則命令將失敗,但不會報錯版确。
注意扣囊,使用上面的命令,提交 A 將不會包含在 Cherry pick 中绒疗。如果要包含提交 A侵歇,可以使用下面的語法。
git cherry-pick A^..B
3吓蘑、代碼沖突的解決
如果操作過程中發(fā)生代碼沖突惕虑,Cherry pick 會停下來,讓用戶決定如何繼續(xù)操作磨镶。
1)溃蔫、--continue
用戶解決代碼沖突后,第一步將修改的文件重新加入暫存區(qū)(git add .)琳猫,第二步使用下面的命令伟叛,讓 Cherry pick 過程繼續(xù)執(zhí)行。
git cherry-pick --continue
2)脐嫂、--abort
發(fā)生代碼沖突后痪伦,放棄合并侄榴,回到操作前的樣子。
git cherry-pick --abort
3)网沾、--quit
發(fā)生代碼沖突后癞蚕,退出 Cherry pick,但是不回到操作前的樣子辉哥。
git cherry-pick --quit
使用場景
cherry pick 最主要的使用場景大概有:
1桦山、serverB開發(fā)的需求feature1,后來臨時決定要把feature1單獨上serverA醋旦,就可以用cherry pick把feature1的提交單獨摘出來恒水,合并到serverA
2、如果有切錯分支的情況饲齐,比如上游分支原來是master钉凌,不小心切了dev分支,現(xiàn)在要更新到master上面捂人,那只能用cherry-pick把需要提交找出來更新上去御雕。