2011-08-04 81 views
288

我在本地存儲庫上有一堆提交,它們在主題上相似。我想在推送到遠程之前將它們合併爲一個提交。我該怎麼做?我認爲rebase這樣做,但我無法理解文檔。在推送Git之前合併多個提交

+1

有關重新綁定/擠壓任意數量的提交,請參閱[我的回答爲「壓縮/合併/重新綁定任意數量的提交」](http://stackoverflow.com/a/22161885/456814)。 – 2014-04-22 20:35:30

+1

相關[如何使用git來壓縮最後一個X提交的內容?](http://stackoverflow.com/q/5189560/456814)。 – 2014-06-06 08:06:31

回答

449

你想做的事情在git中被稱爲「擠壓」。有很多時候你做這個(太多?)的選擇,但如果你只是希望將所有unpushed提交合併爲單一提交,這樣做:

git rebase -i origin/master 

這將使你的文本編輯器(-i是 「互動」),看起來像這樣的文件:

pick 16b5fcc Code in, tests not passing 
pick c964dea Getting closer 
pick 06cf8ee Something changed 
pick 396b4a3 Tests pass 
pick 9be7fdb Better comments 
pick 7dba9cb All done 

改變所有的picksquash(或s)除了第一個:

pick 16b5fcc Code in, tests not passing 
squash c964dea Getting closer 
squash 06cf8ee Something changed 
squash 396b4a3 Tests pass 
squash 9be7fdb Better comments 
squash 7dba9cb All done 

保存您的文件並退出編輯器。然後將打開另一個文本編輯器,讓您將來自所有提交的提交消息合併爲一個大提交消息。

瞧!谷歌搜索「混帳擠壓」會給你所有其他可用選項的解釋。

+14

'origin/master',你的意思是''?如果上游分支已配置,是隱式還是必須指定它? –

+0

這是減少提交次數的一種很酷的方法,但是如果我只想刪除一個子提交文件,例如:刪除「c964dea更接近」提交中的子提交文件,可以嗎? – Jusleong

+7

使用'fixup'而不是'squash'來跳過創建新提交消息的步驟。最後一個提交消息(「全部完成」)將被自動用於'rebase'創建的最終提交。 – faizal

1

您可能想要使用Interactive Rebasing,這在該鏈接中有詳細描述。

如果您搜索「git rebase interactive」,您可以找到其他好的資源。

24

你可以用git rebase -i做到這一點,傳遞您要的「根」要使用的修訂:

git rebase -i origin/master 

將打開,顯示所有你在最後進行的提交的編輯器窗口提交在origin/master。您可以拒絕提交,壓縮提交到單個提交中,或編輯以前的提交。

有跡象表明,也許可以以更好的方式解釋,並展示一些其他的例子少的資源:

http://book.git-scm.com/4_interactive_rebasing.html

http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html

是前兩個好頁面我能找到。

50

如果你有很多提交的,你只需要壓扁最後X承諾,找到您要開始擠壓並做

git rebase -i <that_commit_id> 

然後描述進行的提交的提交ID在leopd的回答中,將所有pick s更改爲squash es,但第一個除外。

+2

我花了一些時間才弄清楚,但似乎本身不會被壓扁。 – lznt

+2

它應該說:「找到提交的提交ID就在你想壓縮爲一組提交之前」。 – BenjaminBallard

10

我想出了

#!/bin/sh 

message=`git log --format=%B origin..HEAD | sort | uniq | grep -v '^$'` 
git reset --soft origin 
git commit -m "$message" 

聯合收割機,排序,結合並從提交信息的空行。我使用它來對github wiki進行本地更改(使用gollum)

+0

這確實是一個非常聰明的主意! – zatziky

+0

出於某種原因(也許這是我的配置或我使用GIT的方式),origin..HEAD給了我一個模糊的參數錯誤。爲了確保它總是從當前分支的頭部獲取差異,我需要將第一行與'git log'一起調整爲這個'git fetch && git log --format =%B FETCH_HEAD..HEAD' [... ] 首先確保GIT具有所需的最新知識,並創建一個我們可以使用的FETCH_HEAD參考。 –

3

您可以使用交互式Rebase進行壓制(加入)提交。有一個相當不錯的YouTube視頻展示瞭如何做到這一點在命令行或SmartGit

如果您已經是SmartGit的用戶,那麼你可以選擇你的所有傳出提交(通過按住Ctrl鍵)並打開上下文菜單(右鍵單擊)壓縮提交。

這是很舒服:

enter image description here

還有來自Atlassian一個很好的教程,說明它是如何工作的:

5

而我的squashing方式多個push是(也許是你推送到你自己的分支許多提交,現在你希望做一個pull請求,你不想用許多你已經推送的提交混淆它們)。我這樣做的方式(據我所知,沒有其他更簡單的選項)。

  1. 爲了squash(從您希望提出請求的原始分支分支)創建新分支。
  2. 推送新創建的分支。
  3. 合併與提交(已推)到新分支的分支。
  4. 重新建立新的分支和壁球。
  5. 推新分支。
  6. 爲現在具有單個提交的新分支創建新的請求。

例子:

git checkout from_branch_you_wish_to_pull_request_to 
git checkout -b new_branch_will_have_single_squashed_commit 
git push -u new_branch_will_have_single_squashed_commit 
git merge older_branch_with_all_those_multiple_commits 
git rebase -i (here you squash) 
git push origin new_branch_will_have_single_squashed_commit 

您現在可以拉請求轉換成from_branch_you_wish_to_pull_request_to

20

有相當多的工作答案在這裏,但我發現這個最簡單的。此命令將打開一個編輯器,在這裏你可以與squash爲了消除只需更換pick /將它們合併成一個

git rebase -i HEAD~4 

其中,4是要擠進一個提交的數目。這也解釋爲here