2008-12-12 11 views
42

下面是一個例子:如何使用'git rebase -i'來重定義分支中的所有更改?

>git status 
# On branch master 
nothing to commit (working directory clean) 
>git checkout -b test-branch 
>vi test.c 
>git add test.c 
>git commit -m "modified test.c" 
>vi README 
>git add README 
>git commit -m "modified README" 

現在我想要做一個「git rebase -i」,讓我重訂所有提交的這個分支。有沒有像'git rebase -i HEAD~MASTER'或類似的東西。我想我可以做'git rebase -i HEAD~2',但我真的不想要計算已經提交了多少次提交。我也可以'git rebase -i sha1',但我不想梳理通過git日誌找到第一個提交sha1。有任何想法嗎?

+1

請標題你的問題好一點。也許提到你想爲分支中的所有更改做一個交互式重新分配。最好以問題的形式(儘管並非總是可行)。 – Dustin 2008-12-12 20:58:12

+0

你想重新綁定到一個修改過的`master`上,或者只是編輯剛剛在`test-branch`上做出的提交? – DylanYoung 2017-11-10 18:12:23

回答

32

你試過了嗎:git rebase -i master

+0

我剛剛在我的示例存儲庫中測試了它,它可以工作。 – Otto 2008-12-14 03:47:24

+14

如果主服務器位於分支當前合併基地之前,則會失敗。 – 2012-08-30 17:14:29

+3

`git rebase -i master`的問題在於你可能已經合併了此時不一定要處理的衝突,或者你可以在一次提交中修復衝突,僅在另一次提交時再修復衝突在rebase期間。我已經添加了一個可以替代這個的答案,並且提供了一個替代方法來指定您希望重定位的確切提交或提交數量。 – 2015-06-24 20:47:34

17

在其他平臺上使用gitk(* nix)或gitx(OS X)或類似軟件,並查看哪些提交是分支的根。然後運行:

git rebase -i <the SHA hash of the root commit> 

例如,我有我使用gitx檢查存儲庫:

gitx screencap http://img.skitch.com/20081213-mq7qpp5nhceksdhfx14rerjgyx.jpg

現在我知道了根散列我可以運行此:

git rebase -i 38965ed29d89a4136e47b688ca10b522b6bc335f 

我的編輯彈出了這個,我可以重新排列/壓扁/任何我喜歡的。

pick 50b2cff File 1 changes. 
pick 345df08 File 2 changes. 
pick 9894931 File 3 changes. 
pick 9a62b92 File 4 changes. 
pick 640b1f8 File 5 changes. 
pick 1c437f7 File 6 changes. 
pick b014597 File 7 changes. 
pick b1f52bc File 8 changes. 
pick 40ae0fc File 9 changes. 

# Rebase 38965ed..40ae0fc onto 38965ed 
# 
# Commands: 
# pick = use commit 
# edit = use commit, but stop for amending 
# squash = use commit, but meld into previous commit 
# 
# If you remove a line here THAT COMMIT WILL BE LOST. 
# However, if you remove everything, the rebase will be aborted. 
# 

我敢肯定有一些神奇的方式來說服git的自動計算出樹的根,但我不知道它是什麼。

編輯:那神奇的是這樣的:

git log master..other_feature | cat 

它會顯示你的那個分支的所有提交和管道貓將禁用尋呼機,所以你看到的第一個立即提交。

編輯:組合上述給出了一個完全自動化的解決方案:

git rebase -i `git log master..other_feature --pretty=format:"%h" | tail -n 1`~ 
+4

-1 OP表示他不想拖網通過日誌 – 2012-08-30 17:11:17

+0

`| |當你可以使用`git --no-pager`時,貓似乎是無用的貓。 – 2015-05-05 06:06:21

44

確定,我asuming分支被稱爲「功能」,它是由「主」支鏈的。

有一個叫做merge-base的小git命令。它需要兩次提交,併爲您提供這兩者的第一個共同祖先。所以...

git merge-base feature master 

...會給你這兩個提交的第一個共同的祖先。想,當你傳遞承諾的Git變基-i,像發生了什麼......

git rebase -i `git merge-base feature master` 

互動從主機和功能分支的共同祖先變基。 利潤! ;)

1

的一般解(如果你不知道上游分支的名字)是:

git rebase -i @{upstream} 

需要注意的是,如果你的上游(可能在跟蹤分支)已經更新了自上次重訂基期,你會從上游提交新的提交。如果你不想拉新的提交,使用

git rebase -i `git merge-base --all HEAD @{upstream}` 

但這是一個有點口。

0
git rebase -i --onto @{u}... @{u} 

從HEAD及其上游的單個合併點開始的交互式重新分配,包括HEAD中不在其上游的所有提交。

換句話說,正是你想要的。

4

由於Git v1.7.10,您可以不帶參數運行git rebase,它會在上游分支上找到叉點並重新綁定您的本地更改。

您需要配置上游分支以使其工作(即無需參數的git pull應該可以工作)。

有關更多細節,參見文檔爲git rebase

如果未指定,則在上游 branch..remote和branch..merge選項來配置將被使用(見 GIT-配置[ 1],並假定--fork-point選項。如果 您目前沒有在任何分支上,或者如果當前分支沒有 具有已配置的上游,那麼rebase將中止。

38

所有提供的解決方案的問題是,它們不允許您從第一次提交開始重新分配。 如果第一次提交哈希值是XYZ和你做:

git rebase -i XYZ 

僅僅衍合從2開始提交。

如果你想從衍合第一承諾你:

git rebase -i --root 
4

從不同的分支

與基礎重建的問題

git rebase -i master的問題是,你可能有合併衝突,你現在不一定需要處理,或者您可以在一次提交中修復衝突,但只能在修復過程中的另一次提交中再次修復衝突。

利用公知衍合的問題提交

這裏的整個問題是,你必須要知道其中承諾,你必須是指,無論是它的SHA,或者HEAD〜x等這只是一個小小的煩惱,但這是一個煩惱。

更好的方法

如果你不是要重訂的所有提交當前分支,自從最近提交它與其父分支共享,可以將以下別名添加到。gitconfig:

rbi = !sh -c \"git rebase -i `git merge-base $1 HEAD`\" - 

使用

git rbi parentBranch 

它是如何工作

這個別名僅僅是一個shell腳本,正在使用它指的是父分支的參數。該參數被傳遞到git merge-base以確定該分支與當前分支之間最近的共享提交。