簡體   English   中英

git rebase 交互:將提交合並在一起

[英]git rebase interactive: squash merge commits together

我想有一個簡單的解決方案來在交互式 rebase 期間將兩個合並提交壓縮在一起。

我的存儲庫看起來像:

   X --- Y --------- M1 -------- M2 (my-feature)
  /                 /           /
 /                 /           /
a --- b --- c --- d --- e --- f (stable)

也就是說,我有一個my-feature分支,最近被合並了兩次,中間沒有真正的提交。 我不只是想 rebase my-feature分支,因為它是它自己的已發布分支,我只想將最后兩個合並提交合並為一個(尚未發布這些提交)

   X --- Y ---- M (my-feature)
  /            /
 /            /
a --- ... -- f (stable)

我試過:

git rebase -p -i M1^

但我得到了:

Refusing to squash a merge: M2

我最后做的是:

git checkout my-feature
git reset --soft HEAD^  # remove the last commit (M2) but keep the changes in the index
git commit -m toto      # redo the commit M2, this time it is not a merge commit
git rebase -p -i M1^    # do the rebase and squash the last commit
git diff M2 HEAD        # test the commits are the same

現在,新的合並提交不再被視為合並提交(它只保留了第一個父項)。 所以:

git reset --soft HEAD^               # get ready to modify the commit
git stash                            # put away the index
git merge -s ours --no-commit stable # regenerate merge information (the second parent)
git stash apply                      # get the index back with the real merge in it
git commit -a                        # commit your merge
git diff M2 HEAD                     # test that you have the same commit again

但是如果我有很多提交,這會變得復雜,你有更好的解決方案嗎? 謝謝。

米爾德里德

這是一個古老的話題,但我只是在尋找類似的信息時遇到了它。

Subtree octopus merge中描述的技巧類似的技巧是解決此類問題的一個非常好的解決方案:

git checkout my-feature
git reset --soft Y
git rev-parse f > .git/MERGE_HEAD
git commit

這將使得索引存在於我的特征的頂端,並使用它來創建一個新的Y提交,其中'f'作為第二個父級。 結果就像你從未執行過M1一樣,但直接執行M2。

如果您尚未發布最后兩個合並提交,則可以執行重置和簡單合並。

git reset --hard Y
git merge stable

我來到這個主題想要壓縮單個合並提交; 所以我的答案對原始問題沒那么有用。

               X
                \   
                 \  
a --- b --- c --- M1 (subtree merge)

我想要的是重新定義M1合並並將所有內容壓縮為b之上的單個提交。

a --- b --- S (include the changes from c, X and M1)

我嘗試了各種不同的組合,但這是有效的:

git checkout -b rebase b (checkout a working branch at point b)
git merge --squash M1

這會將更改應用到可以提交git commit的索引中

使用原始合並提交的樹對象將確保內容保持不變。 commit-tree 可用於具有所需父項和相同內容的新提交。 但是,要使 fmt-merge-msg 生成正常的合並消息,您需要先軟重置回 Y。以下是所有內容與通用配方打包在一起:

parent2=$(git rev-parse f)
parent1=Y
merge_branch=stable
tree=$(git rev-parse HEAD^{tree})
git reset --soft $parent1
commit=$(echo $parent$'\t\t'"branch '$merge_branch'" | git fmt-merge-msg | git commit-tree -p $parent1 -p $parent2 -F - $tree
git reset --hard $commit

在我看來,最好的方法是將自己置於合並提交之上並撤消最高提交並修改對先前合並提交的更改。

您將使用以下命令撤消 git-commit:

    git reset HEAD~1

或者

    git reset HEAD^

然后使用:

    git add . && git commit --amend

然后檢查結果:

    git log

您應該看到第一個合並提交現在包含兩個更改。

此方法可用於所有類型的提交的任何此類需求,或者當

 git rebase -i HEAD~10

... 不能使用。

使用最近的git版本,所提到的方法都不適用於我。 在我的情況下,以下做了訣竅:

git reset --soft Y
git reset --hard $(git commit-tree $(git write-tree) -p HEAD -p stable < commit_msg)

但是,您必須首先將提交消息寫入文件commit_msg。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM