?
このドキュメントでは、 php中國(guó)語(yǔ)ネットマニュアル リリース
git-rebase - 重新申請(qǐng)?zhí)峤涣硪粋€(gè)基本技巧
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>] [<upstream> [<branch>]]git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]git rebase --continue | --skip | --abort | --quit | --edit-todo
如果指定 <branch> ,git rebase
則在執(zhí)行其他任何操作之前將執(zhí)行自動(dòng)操作git checkout <branch>
。否則它將保留在當(dāng)前分支上。
如果未指定 <upstream> ,則將使用在分支。<name> .remote和分支。<name> .merge 選項(xiàng)中配置的上游(有關(guān)詳細(xì)信息,請(qǐng)參閱 git-config [1]),且--fork-point
假定該選項(xiàng)。如果您當(dāng)前沒(méi)有在任何分支上,或者當(dāng)前分支沒(méi)有配置上游,那么 rebase 會(huì)中止。
所有由當(dāng)前分支提交但不在 <upstream> 中的更改都保存到臨時(shí)區(qū)域。這與將要顯示的一組提交相同git log <upstream>..HEAD
; 或者通過(guò)git log 'fork_point'..HEAD
,如果--fork-point
處于活動(dòng)狀態(tài)(請(qǐng)參閱--fork-point
下面的說(shuō)明); 或者,如果--root
指定了選項(xiàng),則git log HEAD
。
如果提供了 --onto 選項(xiàng),則當(dāng)前分支將重置為 <upstream> 或 <newbase> 。這與git reset --hard <upstream>
(或<newbase>)具有完全相同的效果。ORIG_HEAD 被設(shè)置為在復(fù)位之前指向分支的尖端。
之前保存到臨時(shí)區(qū)域的提交按順序依次重新應(yīng)用到當(dāng)前分支。請(qǐng)注意,HEAD 中提交的任何提交與 HEAD .. <upstream> 中的提交相同的文本更改均被省略(即,已經(jīng)接受上游提供不同提交消息或時(shí)間戳的補(bǔ)丁將被跳過(guò))。
合并失敗可能會(huì)阻止此過(guò)程完全自動(dòng)化。您將不得不解決任何此類(lèi)合并失敗并運(yùn)行git rebase --continue
。另一種選擇是繞過(guò)導(dǎo)致合并失敗的提交git rebase --skip
。要檢出原始 <branch> 并刪除 .git / rebase-apply 工作文件,請(qǐng)改用命令git rebase --abort
。
假設(shè)存在以下歷史記錄,并且當(dāng)前分支是“topic”:
A---B---C topic / D---E---F---G master
從這一點(diǎn)來(lái)看,以下任一命令的結(jié)果:
git rebase master git rebase master topic
將會(huì)是:
A'--B'--C' topic / D---E---F---G master
注:后一種形式只是一個(gè)速記git checkout topic
,接著git rebase master
。退出topic
分支時(shí)仍保留退出分支。
如果上游分支已經(jīng)包含您所做的更改(例如,因?yàn)槟]寄了上游應(yīng)用的補(bǔ)?。?,則該提交將被跳過(guò)。例如,運(yùn)行git rebase master
以下歷史記錄(其中A'
并A
引入相同的一組更改,但具有不同的提交者信息):
A---B---C topic / D---E---A'---F master
結(jié)果會(huì)是:
B'---C' topic / D---E---A'---F master
這里是如何將基于一個(gè)分支的主題分支移植到另一個(gè)分支,假裝你使用后者分支從后一分支分支的主題分支rebase --onto
。
首先讓我們假設(shè)你topic
是基于分支的next
。例如,開(kāi)發(fā)的功能topic
取決于可以在其中找到的某些功能next
。
o---o---o---o---o master \ o---o---o---o---o next \ o---o---o topic
我們想topic
從分支中分出來(lái)master
; 例如,因?yàn)?code>topic依賴(lài)的功能被合并到更穩(wěn)定的master
分支中。我們希望我們的樹(shù)看起來(lái)像這樣:
o---o---o---o---o master | \ | o'--o'--o' topic \ o---o---o---o---o next
我們可以使用以下命令來(lái)獲取它:
git rebase --onto master next topic
另一個(gè)例子 --onto 選項(xiàng)是重新綁定分支的一部分。如果我們有以下情況:
H---I---J topicB / E---F---G topicA / A---B---C---D master
然后命令
git rebase --onto master topicA topicB
會(huì)導(dǎo)致:
H'--I'--J' topicB / | E---F---G topicA |/ A---B---C---D master
當(dāng) topicB 不依賴(lài)于 topicA 時(shí),這很有用。
一系列的提交也可以用 rebase 去除。如果我們有以下情況:
E---F---G---H---I---J topicA
然后命令
git rebase --onto topicA~5 topicA~3 topicA
會(huì)導(dǎo)致提交 F 和 G 被移除:
E---H'---I'---J' topicA
如果 F 和 G 以某種方式存在缺陷,或者不應(yīng)該成為 topicA 的一部分,這很有用。請(qǐng)注意,--onto 和 <upstream> 參數(shù)的參數(shù)可以是任何有效的 commit-ish 。
如果發(fā)生沖突,git rebase
將停在第一個(gè)有問(wèn)題的提交并在樹(shù)中留下沖突標(biāo)記。您可以使用git diff
找到標(biāo)記(<<<<<<)并進(jìn)行編輯以解決沖突。對(duì)于你編輯的每一個(gè)文件,你都需要告訴 Git 沖突已經(jīng)解決,通常這是可以完成的
git add <filename>
手動(dòng)解決沖突并以所需的分辨率更新索引后,您可以繼續(xù)使用重新綁定過(guò)程
git rebase --continue
另外,您也可以撤消git rebase
git rebase --abort
rebase.stat
是否顯示自上次變基期以來(lái)上游變化的差異。默認(rèn)為 False 。
rebase.autoSquash
如果--autosquash
默認(rèn)設(shè)置為 true 啟用選項(xiàng)。
rebase.autoStash
如果--autostash
默認(rèn)設(shè)置為 true 啟用選項(xiàng)。
rebase.missingCommitsCheck
如果設(shè)置為 “warn” ,則在交互模式下打印有關(guān)移除提交的警告。如果設(shè)置為 “error” ,請(qǐng)打印警告并停止重設(shè)。如果設(shè)置為 “ignore” ,則不進(jìn)行檢查。默認(rèn)情況下 “ignore” 。
rebase.instructionFormat
自定義提交列表格式,用于重新--interactive
綁定。
--onto <newbase>
創(chuàng)建新提交的起點(diǎn)。如果沒(méi)有指定 --onto 選項(xiàng),起點(diǎn)是 <upstream> ??梢允侨魏斡行У奶峤唬粌H僅是現(xiàn)有的分支名稱(chēng)。
作為特例,如果只有一個(gè)合并基礎(chǔ),則可以使用“A ... B”作為 A 和 B 合并基的快捷方式。您最多可以省略 A 和 B 中的一個(gè),在這種情況下,它默認(rèn)為 HEAD 。
<upstream>
上游分支進(jìn)行比較??梢允侨魏斡行У奶峤?,而不僅僅是現(xiàn)有的分支名稱(chēng)。默認(rèn)為當(dāng)前分支的配置上游。
<branch>
工作分部; 默認(rèn)為 HEAD 。
--continue
解決了合并沖突后重新啟動(dòng)重新綁定過(guò)程。
--abort
中止 rebase 操作并將 HEAD 重置為原始分支。如果 <reb> 操作開(kāi)始時(shí)提供 <branch> ,則 HEAD 將重置為 <branch> 。否則 HEAD 將重置為啟動(dòng) rebase 操作時(shí)的位置。
--quit
放棄 rebase 操作,但 HEAD 不會(huì)重置回原始分支。索引和工作樹(shù)也因此保持不變。
--keep-empty
在結(jié)果中保留不改變父項(xiàng)的任何提交。
--skip
通過(guò)跳過(guò)當(dāng)前補(bǔ)丁重新啟動(dòng)重新綁定過(guò)程。
--edit-todo
在交互式重新綁定期間編輯待辦事項(xiàng)列表。
-m --merge
使用合并策略來(lái)重新分配。當(dāng)使用遞歸(默認(rèn))合并策略時(shí),這允許 rebase 知道上游端的重命名。
請(qǐng)注意,通過(guò)在 <upstream> 分支頂部重播來(lái)自工作分支的每個(gè)提交,合并索引合并工作。正因?yàn)槿绱耍?dāng)合并沖突發(fā)生時(shí),該方報(bào)告的ours
是迄今為止重新分類(lèi)的系列,從 <upstream> 開(kāi)始,并且theirs
是工作分支。換句話(huà)說(shuō),雙方交換。
-s <strategy> --strategy=<strategy>
使用給定的合并策略。如果沒(méi)有-s
選項(xiàng)git merge-recursive
用來(lái)代替。這意味著 - 合并。
因?yàn)?code>git rebase使用給定的策略,重播每個(gè)都會(huì)在 <upstream> 分支之上的工作分支提交,所以使用該ours
策略只會(huì)丟棄 <branch> 中的所有修補(bǔ)程序,這沒(méi)有多大意義。
-X <strategy-option> --strategy-option=<strategy-option>
將 <strategy-option> 傳遞給合并策略。這意味著--merge
,如果沒(méi)有明確說(shuō)明戰(zhàn)略-s recursive
。請(qǐng)注意該選項(xiàng)的逆轉(zhuǎn)ours
和theirs
上面所述-m
。
-S<keyid> --gpg-sign=<keyid>
GPG 標(biāo)志提交。該keyid
參數(shù)是可選的,并且默認(rèn)為提交者身份; 如果指定,它必須粘貼到選項(xiàng)沒(méi)有空格。
-q --quiet
be quiet。意味著 -- 無(wú)統(tǒng)計(jì)。
-v --verbose
詳細(xì)。意味著--要統(tǒng)計(jì)。
--stat
顯示自上次 rebase 以來(lái)上游變化的差異。diffstat 也由配置選項(xiàng) rebase.stat 控制。
-n --no-stat
不要將 diffstat 顯示為 rebase 過(guò)程的一部分。
--no-verify
此選項(xiàng)繞過(guò)預(yù)先重新綁定鉤子。另見(jiàn) githooks [5]。
--verify
允許預(yù)重貼掛鉤運(yùn)行,這是默認(rèn)設(shè)置。這個(gè)選項(xiàng)可以用來(lái)覆蓋--no-verify 。另見(jiàn) githooks [5] 。
-C<n>
確保每次更改之前和之后至少有 <n> 行周?chē)h(huán)境匹配。當(dāng)存在較少的周?chē)h(huán)境線(xiàn)時(shí),它們都必須匹配。默認(rèn)情況下,不會(huì)忽略上下文。
-f --force-rebase
即使當(dāng)前分支是最新的,并且--force
沒(méi)有做任何事情的命令也不會(huì)返回,強(qiáng)制重新分配。
你可能會(huì)發(fā)現(xiàn)這個(gè)(或者 --no-ff 帶有交互式底座)在恢復(fù)主題分支合并之后很有用,因?yàn)檫@個(gè)選項(xiàng)用新提交重新創(chuàng)建了主題分支,所以它可以在不需要“還原返回”的情況下成功地重新建立。在還原-A-錯(cuò)誤的合并操作方法的詳細(xì)說(shuō)明)。
--fork-point --no-fork-point
計(jì)算 <branch> 引入的提交時(shí),使用 reflog 可以在 <upstream> 和 <branch> 之間找到更好的共同祖先。
當(dāng) --fork-point 被激活時(shí),fork_point
將被用來(lái)代替<upstream>來(lái)計(jì)算 rebase 的提交集合fork_point
,git merge-base --fork-point <upstream> <branch>
命令的結(jié)果在哪里(參見(jiàn) git-merge-base [1])。如果fork_point
結(jié)果為空,<upstream> 將用作后備。
如果在命令行中給出了 <upstream> 或 --root ,則默認(rèn)為--no-fork-point
,否則為默認(rèn)值--fork-point
。
--ignore-whitespace --whitespace=<option>
這些標(biāo)志被傳遞給git apply
應(yīng)用該補(bǔ)丁的程序(參見(jiàn) git-apply [1])。與 --interactive 選項(xiàng)不兼容。
--committer-date-is-author-date --ignore-date
這些標(biāo)志被傳遞給git am
輕松更改重定義的提交的日期(請(qǐng)參閱 git-am [1])。與 --interactive 選項(xiàng)不兼容。
--signoff
這個(gè)標(biāo)志被傳遞來(lái)git am
簽署所有重新發(fā)布的提交(參見(jiàn) git-am [1])。與 --interactive 選項(xiàng)不兼容。
-i --interactive
列出將要重新分配的提交列表。讓用戶(hù)在重新綁定之前編輯該列表。該模式也可用于分割提交(請(qǐng)參閱下面的分割提交)。
提交列表格式可以通過(guò)設(shè)置配置選項(xiàng) rebase.instructionFormat 進(jìn)行更改。自定義的指令格式會(huì)自動(dòng)將格式中的長(zhǎng)提交哈希值作為前綴。
-p --preserve-merges
重新創(chuàng)建合并提交,而不是通過(guò)重播合并提交引入的提交來(lái)平坦化歷史。不保留合并沖突解決方案或手動(dòng)修改合并提交。
這在--interactive
內(nèi)部使用機(jī)制,但--interactive
明確地將其與選項(xiàng)結(jié)合通常不是一個(gè)好主意,除非您知道自己在做什么(請(qǐng)參閱下面的 BUGS )。
-x <cmd> --exec <cmd>
在每行在最終歷史記錄中創(chuàng)建提交后附加 “exec <cmd>” 。<cmd> 將被解釋為一個(gè)或多個(gè) shell 命令。
您可以通過(guò)使用幾個(gè)命令的一個(gè)實(shí)例來(lái)--exec
執(zhí)行幾個(gè)命令:
git rebase -i --exec "cmd1 && cmd2 && ..."
或者通過(guò)給予多個(gè)--exec
:
git rebase -i --exec "cmd1" --exec "cmd2" --exec ...
如果--autosquash
使用,中間提交不會(huì)追加 “exec” 行,并且只會(huì)出現(xiàn)在 squash / fixup 系列的末尾。
這在--interactive
內(nèi)部使用機(jī)制,但它可以在沒(méi)有明確的情況下運(yùn)行--interactive
。
--root
重新規(guī)劃從 <branch> 可訪(fǎng)問(wèn)的所有提交,而不是用 <upstream> 限制它們。這允許您重新分支分支上的根提交。當(dāng)與 --onto 一起使用時(shí),它將跳過(guò)已包含在 <newbase>(而不是 <upstream> )中的更改,而不使用 - 將在每次更改時(shí)運(yùn)行。當(dāng)與 --onto 和 --preserve-merges 一起使用時(shí),all
根提交將被重寫(xiě)為具有 <newbase> 作為父代。
--autosquash --no-autosquash
當(dāng)提交日志消息以“squash!...”(或“fixup!...”)開(kāi)始,并且存在一個(gè)標(biāo)題以相同的開(kāi)頭的提交時(shí),自動(dòng)修改 rebase -i 的待辦事項(xiàng)列表,以便提交標(biāo)記為壓扁,在提交被修改后立即出現(xiàn),并將移動(dòng)的提交的操作從(或)pick
改為。在第一次之后忽略隨后的“fixup!”或“squash!”,以防您提到之前的 fixup / squash 。squashfixupgit commit --fixup/--squash
該選項(xiàng)僅在使用該--interactive
選項(xiàng)時(shí)有效。
如果該--autosquash
選項(xiàng)默認(rèn)情況下使用配置變量啟用rebase.autoSquash
,則此選項(xiàng)可用于覆蓋和禁用此設(shè)置。
--autostash --no-autostash
在操作開(kāi)始之前自動(dòng)創(chuàng)建臨時(shí)存儲(chǔ)條目,并在操作結(jié)束后應(yīng)用它。這意味著你可以在骯臟的工作樹(shù)上運(yùn)行 rebase 。但是,謹(jǐn)慎使用:成功重新綁定后的最終隱藏應(yīng)用程序可能會(huì)導(dǎo)致不平凡的沖突。
--no-ff
使用 -interactive ,cherry-pick 所有重新提交的提交,而不是對(duì)未更改的提交進(jìn)行快速轉(zhuǎn)發(fā)。這確保了重新分支的整個(gè)歷史由新的提交組成。
Without --interactive ,這是 --force-rebase 的同義詞。
在恢復(fù)主題分支合并之后,您可能會(huì)發(fā)現(xiàn)這很有幫助,因?yàn)榇诉x項(xiàng)重新創(chuàng)建了具有新提交的主題分支,因此可以在不需要“還原返回”的情況下成功重新分配(請(qǐng)參閱恢復(fù) - 錯(cuò)誤 - 合并的方法細(xì)節(jié))。
合并機(jī)制(git merge
和git pull
命令)允許merge strategies
使用-s
選項(xiàng)選擇后端。一些策略也可以采取他們自己的選擇,可以通過(guò)給git merge
和/或git pull
給出-X<option>
參數(shù)來(lái)傳遞。
resolve
這只能使用3路合并算法來(lái)解析兩個(gè)頭(即當(dāng)前分支和您從其中取出的另一個(gè)分支)。它試圖仔細(xì)檢測(cè)交叉融合歧義,并被認(rèn)為通常是安全和快速的。
recursive
這只能使用3路合并算法來(lái)解析兩個(gè)頭。當(dāng)有多個(gè)可用于3路合并的共同祖先時(shí),它將創(chuàng)建共同祖先的合并樹(shù)并將其用作3路合并的參考樹(shù)。據(jù)報(bào)道,這會(huì)導(dǎo)致更少的合并沖突,而不會(huì)因從 Linux 2.6內(nèi)核開(kāi)發(fā)歷史記錄中進(jìn)行的實(shí)際合并提交所做的測(cè)試而導(dǎo)致混淆。此外,這可以檢測(cè)并處理涉及重命名的合并。這是拉取或合并一個(gè)分支時(shí)的默認(rèn)合并策略。
該recursive
策略可以采取以下選擇:
ours
該選項(xiàng)強(qiáng)制沖突的 hunk 通過(guò)支持our
版本自動(dòng)解決。來(lái)自另一棵與我們不沖突的樹(shù)的變化反映到合并結(jié)果。對(duì)于二進(jìn)制文件,整個(gè)內(nèi)容都是從我們這邊拿來(lái)的。
這不應(yīng)與ours
合并策略混淆,合并策略甚至不會(huì)考慮其他樹(shù)包含的內(nèi)容。它丟棄了其他樹(shù)的所有內(nèi)容,聲明our
歷史包含發(fā)生在其中的所有事情。
theirs
這是與ours
相反的; 請(qǐng)注意,與此不同的ours
是,沒(méi)有theirs
融合策略來(lái)混淆這個(gè)合并選項(xiàng)。
patience
使用此選項(xiàng),merge-recursive
花費(fèi)一點(diǎn)額外的時(shí)間來(lái)避免由于不重要的匹配行(例如,來(lái)自不同功能的括號(hào))而導(dǎo)致的混淆。當(dāng)要合并的分支瘋狂地分歧時(shí)使用它。另請(qǐng)參閱 git-diff [1] --patience
。
diff-algorithm=patience|minimal|histogram|myers
告訴merge-recursive
使用不同的差異算法,這可以幫助避免由于不重要的匹配行(例如不同功能的花括號(hào))而發(fā)生誤合。另請(qǐng)參閱 git-diff [1] --diff-algorithm
。
ignore-space-change ignore-all-space ignore-space-at-eol
為了三路合并的目的,將指定類(lèi)型的空白的行對(duì)待不變??瞻鬃兓c其他變化混合在一起不會(huì)被忽略。另見(jiàn) GIT-DIFF [1] ,-b
,-w
和--ignore-space-at-eol
。
如果their
版本只對(duì)一行引入空白變化,our
則使用版本;
如果our
版本引入空白變化,但their
版本包含實(shí)質(zhì)性更改,their
則使用版本;
否則,合并按照通常的方式進(jìn)行。
renormalize
這將在解析三路合并時(shí)運(yùn)行虛擬檢出和檢入文件的所有三個(gè)階段。此選項(xiàng)用于合并具有不同干凈過(guò)濾器或行結(jié)束標(biāo)準(zhǔn)化規(guī)則的分支時(shí)使用。有關(guān)詳細(xì)信息,請(qǐng)參閱 gitattributes [5]中的“合并不同簽入/簽出屬性的分支”。
no-renormalize
禁用該renormalize
選項(xiàng)。這覆蓋merge.renormalize
配置變量。
no-renames
關(guān)閉重命名檢測(cè)。另請(qǐng)參閱 git-diff [1] --no-renames
。
find-renames=<n>
打開(kāi)重命名檢測(cè),可選擇設(shè)置相似性閾值。這是默認(rèn)設(shè)置。另請(qǐng)參閱 git-diff [1] --find-renames
。
rename-threshold=<n>
已棄用的同義詞find-renames=<n>
。
subtree=<path>
該選項(xiàng)是一種更高級(jí)的subtree
策略形式,該策略可以猜測(cè)兩個(gè)樹(shù)在合并時(shí)必須如何移動(dòng)以相互匹配。相反,指定的路徑是前綴(或從開(kāi)始剝離)以使兩棵樹(shù)的形狀匹配。
octopus
這解決了兩個(gè)以上負(fù)責(zé)人的情況,但拒絕執(zhí)行需要手動(dòng)解決的復(fù)雜合并。它主要用于將主題分支主題捆綁在一起。這是拉取或合并多個(gè)分支時(shí)的默認(rèn)合并策略。
ours
這可以解析任意數(shù)量的頭,但合并結(jié)果樹(shù)始終是當(dāng)前分支頭的樹(shù),有效地忽略了來(lái)自所有其他分支的所有更改。它是用來(lái)取代側(cè)枝的舊發(fā)展歷史。請(qǐng)注意,這與recursive
合并策略的 -Xours 選項(xiàng)不同。
subtree
這是一個(gè)修改后的遞歸策略。當(dāng)合并樹(shù) A 和 B 時(shí),如果 B 對(duì)應(yīng)于 A 的子樹(shù),則首先調(diào)整 B 以匹配 A 的樹(shù)結(jié)構(gòu),而不是讀取處于相同級(jí)別的樹(shù)。這種調(diào)整也對(duì)共同的祖先樹(shù)進(jìn)行。
對(duì)于使用3路合并(包括默認(rèn)值recursive
)的策略,如果在兩個(gè)分支上進(jìn)行了更改,但稍后在其中一個(gè)分支上進(jìn)行了恢復(fù),則該更改將出現(xiàn)在合并結(jié)果中; 有些人覺(jué)得這種行為很混亂。這是因?yàn)樵趫?zhí)行合并時(shí)僅考慮頭部和合并基礎(chǔ),而不是個(gè)別提交。因此,合并算法將恢復(fù)的更改視為完全沒(méi)有更改,而是替換更改的版本。
您應(yīng)該了解在git rebase
共享的存儲(chǔ)庫(kù)上使用的含義。請(qǐng)參閱下面的“從上游重新啟動(dòng)”中恢復(fù)。
當(dāng) git-rebase 命令運(yùn)行時(shí),它會(huì)首先執(zhí)行一個(gè) “pre-rebase” 掛鉤(如果存在)。您可以使用此掛鉤進(jìn)行健全性檢查,并在不合適的情況下拒絕 rebase 。有關(guān)示例,請(qǐng)參閱模板 pre-rebase 掛鉤腳本。
完成后,<branch> 將成為當(dāng)前分支。
交互式重新定位意味著您有機(jī)會(huì)編輯重新提交的提交。您可以對(duì)提交進(jìn)行重新排序,并且可以將其刪除(清除不良或其他不需要的修補(bǔ)程序)。
交互模式適用于這種類(lèi)型的工作流程:
有一個(gè)奇妙的想法
破解代碼
準(zhǔn)備一系列提交
提交
point 2. 由幾個(gè)實(shí)例組成
a)常規(guī)使用
完成值得一提的東西
遞交
b)獨(dú)立修復(fù)
意識(shí)到某些事情不起作用
解決該問(wèn)題
提交它
有時(shí)候在 b.2 中固定的東西。不能修改為它所修復(fù)的不完美的提交,因?yàn)樵撎峤簧钌畹芈袢肓搜a(bǔ)丁系列中。這正是交互式底座的用途:在大量的 “a” 和 “b” 之后使用它,重新安排和編輯提交,并將多個(gè)提交壓縮成一個(gè)。
按照原樣保留的最后一次提交啟動(dòng)它:
git rebase -i <after-this-commit>
編輯器將會(huì)觸發(fā)當(dāng)前分支中的所有提交(忽略合并提交),這些提交會(huì)在給定的提交之后提交。您可以將此列表中的提交重新排序,直至您的內(nèi)容為準(zhǔn),并且可以將其刪除。該列表看起來(lái)或多或少像這樣:
pick deadbee The oneline of this commit pick fa1afe1 The oneline of the next commit...
在線(xiàn)描述純粹是為了樂(lè)趣; git rebase
將不會(huì)看到它們,而是以提交名稱(chēng)(本例中為 “deadbee” 和 “fa1afe1” ),因此不要?jiǎng)h除或編輯名稱(chēng)。
通過(guò)使用命令 “edit” 替換命令 “pick” ,您可以告訴git rebase
在應(yīng)用該提交后停止,以便您可以編輯文件和/或提交消息,修改提交并繼續(xù)重新綁定。
如果您只想編輯提交的提交消息,請(qǐng)將命令 “pick” 替換為 “reword” 命令。
要?jiǎng)h除提交,請(qǐng)將 “pick” 命令替換為 “drop” ,或者只刪除匹配的行。
如果要將兩個(gè)或多個(gè)提交合并為一個(gè),請(qǐng)將第二個(gè)提交和后續(xù)提交的命令替換為 “squash ”或 “fixup” 。如果提交具有不同的作者,則折疊提交將歸于第一次提交的作者。對(duì)于已提交的提交,建議的提交消息是第一次提交的提交消息和那些使用 “squash” 命令的提交消息的連接,但省略了使用 “fixup” 命令提交的提交消息。
git rebase
將 “pick” 替換為 “edit” 或由于合并錯(cuò)誤而導(dǎo)致命令失敗時(shí)停止。當(dāng)您完成編輯和/或解決沖突時(shí),您可以繼續(xù)git rebase --continue
。
例如,如果您想重新排序最后5次提交,那么 HEAD?4會(huì) 成為新的 HEAD 。要達(dá)到這個(gè)目標(biāo),你可以這樣調(diào)用git rebase
:
$ git rebase -i HEAD~5
并將第一個(gè)補(bǔ)丁移動(dòng)到列表的末尾。
如果您有這樣的歷史記錄,您可能想要保留合并:
X \ A---M---B /---o---O---P---Q
假設(shè)你想重新分支從 “A” 開(kāi)始到 “Q” 的分支。確保當(dāng)前 HEAD 是 “B” ,然后調(diào)用
$ git rebase -i -p --onto Q O
重新排序和編輯提交通常會(huì)創(chuàng)建未經(jīng)測(cè)試的中間步驟。您可能需要檢查歷史編輯是否通過(guò)運(yùn)行測(cè)試,或至少使用 “exec” 命令(快捷方式 “x” )在歷史中間點(diǎn)重新編譯來(lái)破壞任何內(nèi)容。你可以通過(guò)創(chuàng)建一個(gè)像這樣的待辦事項(xiàng)列表來(lái)實(shí)現(xiàn):
pick deadbee Implement feature XXX fixup f1a5c00 Fix to feature XXX exec make pick c0ffeee The oneline of the next commit edit deadbab The oneline of the commit after exec cd subdir; make test...
當(dāng)命令失敗時(shí)(即以非0狀態(tài)退出),交互式重新分配將停止,讓您有機(jī)會(huì)解決問(wèn)題。你可以繼續(xù)git rebase --continue
。
“exec” 命令會(huì)在 shell 中啟動(dòng)該命令(在中指定的命令$SHELL
或默認(rèn) shell ,如果$SHELL
未設(shè)置),因此您可以使用 shell 功能(如“cd”,“>”,“;”...)。該命令從工作樹(shù)的根目錄運(yùn)行。
$ git rebase -i --exec "make test"
這個(gè)命令讓你檢查中間提交是否可編譯。待辦事項(xiàng)列表如下所示:
pick 5928aea one exec make test pick 04d0fda two exec make test pick ba46169 three exec make test pick f4593f9 four exec make test
在交互模式下,您可以使用“編輯”操作標(biāo)記提交。但是,這并不一定意味著git rebase
期望這個(gè)編輯的結(jié)果恰好是一個(gè)提交。事實(shí)上,您可以撤銷(xiāo)提交,也可以添加其他提交。這可以用來(lái)將提交分成兩部分:
開(kāi)始一個(gè)交互式重新綁定git rebase -i <commit>^
,其中 <commit> 是您要分割的提交。實(shí)際上,只要包含該提交,任何提交范圍都會(huì)執(zhí)行。
使用“編輯”操作標(biāo)記要分割的提交。
當(dāng)編輯提交時(shí),執(zhí)行git reset HEAD^
。其效果是 HEAD 被倒回1,并且索引也隨之而來(lái)。但是,工作樹(shù)保持不變。
現(xiàn)在將更改添加到您想要在第一次提交中使用的索引中。您可以使用git add
(可能交互式)或git gui
(或兩者)來(lái)做到這一點(diǎn)。
使用現(xiàn)在適合的提交消息提交當(dāng)前的索引。
重復(fù)最后兩個(gè)步驟,直到你的工作樹(shù)干凈。
繼續(xù)與git rebase --continue
的 rebase 。
如果您不確定中間修訂是否一致(它們會(huì)進(jìn)行編譯,通過(guò)測(cè)試套件等),您應(yīng)該使用git stash
它在每次提交,測(cè)試和修改提交(如果需要修復(fù))后保留尚未提交的更改。
其他人基于工作的分支(或任何其他形式的重寫(xiě))是一個(gè)壞主意:它下游的任何人都被迫手動(dòng)修改其歷史記錄。本節(jié)介紹如何從下游角度進(jìn)行修復(fù)。然而,真正的解決辦法是避免重新擺放上游。
為了說(shuō)明,假設(shè)你處于某人開(kāi)發(fā)subsystem
分支的情況,并且你正在研究一個(gè)topic
依賴(lài)于此的分支subsystem
。你可能會(huì)得到如下的歷史記錄:
o---o---o---o---o---o---o---o master \ o---o---o---o---o subsystem \ *---*---* topic
如果subsystem
重新發(fā)放master
,會(huì)發(fā)生以下情況:
o---o---o---o---o---o---o---o master \ \ o---o---o---o---o o'--o'--o'--o'--o' subsystem \ *---*---* topic
如果你現(xiàn)在繼續(xù)開(kāi)發(fā)像往常一樣,并最終合并topic
到subsystem
,從提交subsystem
會(huì)永遠(yuǎn)保持復(fù)制:
o---o---o---o---o---o---o---o master \ \ o---o---o---o---o o'--o'--o'--o'--o'--M subsystem \ / *---*---*-..........-*--* topic
這些重復(fù)的東西通常會(huì)被忽視,因?yàn)樗鼈兓煜藲v史,使其難以遵循。為了清理,你需要將提交移植topic
到新的subsystem
提示中,即 rebase topic
。這變成了一種連鎖反應(yīng):下游的任何人topic
都被迫變質(zhì),等等!
有兩種修復(fù)方法,將在以下小節(jié)中討論:
簡(jiǎn)單案例:這些變化字面上是相同的。
如果這個(gè)subsystem
rebase 是一個(gè)簡(jiǎn)單的 rebase 并且沒(méi)有沖突,就會(huì)發(fā)生這種情況。
困難的情況:變化是不一樣的。
如果subsystem
rebase 有沖突或者用于--interactive
忽略,編輯,擠壓或修改提交,就會(huì)發(fā)生這種情況; 或者如果上游使用的一個(gè)commit --amend
,reset
或filter-branch
。
只有subsystem
在 rebase subsystem
之前和之后的變化(基于 diff 內(nèi)容的補(bǔ)丁ID)字面上相同時(shí)才有效。
在這種情況下,修復(fù)很容易,因?yàn)?code>git rebase知道跳過(guò)已經(jīng)存在于新上游的變化。所以如果你說(shuō)(假設(shè)你在topic
)
$ git rebase subsystem
你會(huì)以固定的結(jié)果結(jié)束
o---o---o---o---o---o---o---o master \ o'--o'--o'--o'--o' subsystem \ *---*---* topic
如果這些subsystem
變化與 rebase 之前的變化不完全一致,事情會(huì)變得更加復(fù)雜。
Note | While an "easy case recovery" sometimes appears to be successful even in the hard case, it may have unintended consequences. For example, a commit that was removed via git rebase --interactive will be resurrected! |
---|
這個(gè)想法是手動(dòng)告訴git rebase
“舊的subsystem
結(jié)局和你的topic
開(kāi)始”,也就是說(shuō),他們之間的舊合并基礎(chǔ)是什么。您必須找到一種方法來(lái)命名舊的最后一次提交subsystem
,例如:
隨著subsystem
reflog:之后git fetch
,舊的一角subsystem
是在subsystem@{1}
。后續(xù)提取將增加數(shù)量。(請(qǐng)參閱 git-reflog [1]。)
相對(duì)于提示topic
:知道你topic
有三次提交,舊的提示subsystem
必須是topic~3
。
然后你可以subsystem..topic
通過(guò)說(shuō)(對(duì)于 reflog 的情況,并假設(shè)你已經(jīng)topic
),將舊的移植到新的提示中:
$ git rebase --onto subsystem subsystem@{1}
“硬性案例”恢復(fù)的連鎖反應(yīng)特別糟糕:everyone
下游topic
將不得不進(jìn)行“硬性案例”恢復(fù)!
提供的待辦事項(xiàng)列表--preserve-merges --interactive
不代表修訂圖的拓?fù)浣Y(jié)構(gòu)。編輯提交和重新提交它們的提交消息應(yīng)該可以正常工作,但嘗試重新排序提交往往會(huì)產(chǎn)生違反直覺(jué)的結(jié)果。
例如,嘗試重新排列
1 --- 2 --- 3 --- 4 --- 5
至
1 --- 2 --- 4 --- 3 --- 5
通過(guò)移動(dòng) “pick 4” 行,將導(dǎo)致以下歷史記錄:
3 /1 --- 2 --- 4 --- 5