簡體   English   中英

合並(使用壁球)來自另一個分支的所有更改作為單個提交

[英]Merge (with squash) all changes from another branch as a single commit

在 Git 中,有沒有辦法將所有更改從一個分支合並到另一個分支,但同時壓縮到單個提交?

我經常在單獨的分支中開發新功能,並且會定期提交/推送——主要用於備份或將我正在處理的內容轉移到另一台機器上。 大多數提交都說“Feature xxx WIP”或多余的東西。

一旦該工作完成並且我想將 WIP 分支合並回 master,我想丟棄所有這些中間提交,並且只有一個干凈的提交。

是否有捷徑可尋?

或者,從分支點開始壓縮分支上所有提交的命令怎么樣?

另一種選擇是git merge --squash <feature branch>然后最后做一個git commit

Git 合並

--squash

--no-squash

生成工作樹和索引狀態,就好像真正的合並發生一樣(合並信息除外),但不實際提交或移動HEAD ,也不記錄$GIT_DIR/MERGE_HEAD以導致下一個git commit命令創建合並提交。 這允許您在當前分支之上創建單個提交,其效果與合並另一個分支相同(如果是章魚則更多)。

找到了! 合並命令有一個--squash選項

git checkout master
git merge --squash WIP

在這一點上,一切都被合並了,可能是沖突的,但沒有提交。 所以我現在可以:

git add .
git commit -m "Merged WIP"

在您的功能分支上嘗試git rebase -i master 然后,您可以將除一個 'pick' 以外的所有內容更改為 'squash' 以合並提交。 查看使用 rebase 壓縮提交

最后,您可以從 master 分支進行合並。

使用git merge --squash <feature branch>作為已接受的答案表明可以解決問題,但它不會將合並的分支顯示為實際合並。

因此,更好的解決方案是:

  • 創建一個新的分支最新大師 , 在功能分支啟動的主分支中提交。
  • 使用git merge --squash <feature branch>合並到上面
  • 將新創建的分支合並到 master 中。 這樣,功能分支將只包含一個提交,合並將在一個簡短而整潔的插圖中表示。

這個 wiki詳細解釋了這個過程。

在下面的例子中,左手截圖是qgit的結果,右手截圖是以下結果:

git log --graph --decorate --pretty=oneline --abbrev-commit

兩個屏幕截圖都顯示了同一存儲庫中相同范圍的提交。 盡管如此,由於--squash ,正確的更緊湊。

  • 隨着時間的推移, master分支偏離了db
  • db功能准備就緒時,在db具有其根的master的同一提交中創建了一個名為tag的新分支。
  • tag執行git merge --squash db ,然后所有更改都在單個提交中暫存和提交。
  • mastertag被合並: git merge tag
  • 分支search無關緊要,不會以任何方式合並。

在此處輸入圖片說明

2020 更新

使用--squash標志,它看起來像兩個沒有關系的平行分支:

在此處輸入圖片說明

排序與日期相關的提交看起來像:

在此處輸入圖片說明

就個人而言,我不喜歡 --squash 選項,試試這個技巧,也許它適合你的需求,我將它用於小型項目:

  1. 混帳初始化
  2. git checkout -b dev
  3. 開發中的幾次提交
  4. 在 dev 中做了一些很棒的提交(但還沒有合並到 master 中)之后,如果你不想將所有提交復制到 master 分支,那么故意在 master 和(在 README 文件中添加一些空行並在 master 中提交)中進行一些更改,
  5. git merge dev 它導致合並沖突(自述文件中的空行),解決它,用你想要的新消息提交,你就完成了。 這是它的視覺表示。

有意合並沖突的空提交,將其命名為您喜歡的任何名稱

有意合並沖突的空提交

我已經創建了自己的 git 別名來做到這一點。 我稱之為git freebase 它將采用您現有的雜亂的、不可rebase 的功能分支並重新創建它,以便它成為一個具有相同名稱的新分支,其提交被壓縮為一個提交並重新基於您指定的分支(默認情況下為 master)。 最后,它將允許您為新的“freebased”分支使用您喜歡的任何提交消息。

通過在 .gitconfig 中放置以下別名來安裝它:

[alias]
  freebase = "!f() { \
    TOPIC="$(git branch | grep '\\*' | cut -d ' ' -f2)"; \
    NEWBASE="${1:-master}"; \
    PREVSHA1="$(git rev-parse HEAD)"; \
    echo "Freebaseing $TOPIC onto $NEWBASE, previous sha1 was $PREVSHA1"; \
    echo "---"; \
    git reset --hard "$NEWBASE"; \
    git merge --squash "$PREVSHA1"; \
    git commit; \
  }; f"

通過運行從您的功能分支使用它: git freebase <new-base>

我只測試了幾次,所以先閱讀它並確保你想運行它。 作為一項安全措施,它確實打印了起始 sha1,因此如果出現任何問題,您應該能夠恢復舊分支。

我將在 github 上的 dotfiles 存儲庫中維護它: https : //github.com/stevecrozz/dotfiles/blob/master/.gitconfig

您有一個主分支和功能分支。 您在功能分支上有很多提交。 您不希望功能分支的所有提交都出現在 master 的提交歷史記錄中。 按着這些次序

  1. 從最新的主代碼創建一個新分支,您就在該分支中
git checkout -b latest_MCode
  1. 現在將您的功能分支合並到 latest_Mcode 分支
git merge --squash feature
  1. 在沒有 -m 參數的情況下提交

git 提交 # 沒有 -m

編輯器應該是一個包含所有提交日志的彈出窗口,以及從功能分支更改的文件。 您可以在此處查看所有功能分支提交。 如果你願意,你可以刪除所有內容,只寫一行你想在合並到 master 后顯示的提交消息。 按 i 然后寫你的信息然后按 Esc->:wq->Enter 保存並退出編輯器。 4. 將新創建的分支合並到 master

git checkout master
git merge latest_Mcode
git push

你完成了! 原始答案可以在GithubLink找到

git merge --squash <feature branch>是一個不錯的選擇。“git commit”告訴您所有功能分支提交消息,並選擇保留它。

對於較少提交合並。

git merge do x 次 --git reset HEAD^ --soft 然后 git commit 。

風險刪除的文件可能會回來。

我想把我主人的所有提交壓縮成一個。 我沒試成功:

$ git checkout --orphan new_master
$ git merge --squash master
fatal: Squash commit into empty head not supported yet

所以我這樣做了:

$ tar cf /tmp/git.tar --exclude .git .
$ git checkout --orphan new_master
$ tar xf /tmp/git.tar
$ git commit -m "Initial commit"

這很好用。

您可以使用“rebase”命令執行此操作。 讓我們稱分支為“main”和“feature”:

git checkout feature
git rebase main

rebase 命令會將“功能”上的所有提交重放為父項等於“main”的一次提交。

如果“main”自“feature”創建后(或自最近的合並以來)發生了變化,您可能希望在git rebase main git merge main之前運行git merge main 這樣,您仍然擁有完整的歷史記錄,以防發生合並沖突。

在 rebase 之后,您可以將分支合並到主分支,這應該會導致快進合並:

git checkout main
git merge feature

請參閱從概念理解 Gitrebase頁面以獲得一個很好的概述

暫無
暫無

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

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