簡體   English   中英

如何在git中合並提交之前找到兩個分支的共同祖先?

[英]How to find the common ancestor of two branches before a merge commit in git?

背景

我正在嘗試編寫一個腳本,它將使用git簡化我的backport進程。

修復當前版本中的錯誤的一般過程如下:

  1. master到bug修復分支,例如bugfix/abc
  2. 進行所有提交以修復bugfix/abc上的錯誤
  3. bugfix/abc合並到master (沒有快進合並)

現在,當我想將修復程序向后移植到版本1時(分支v1 )我做:

  1. bugfix/abc創建一個新分支,例如bugfix/def
  2. 然后手動查找合並提交之前的master上的提交,例如f4d399238f
  3. 現在我使用rebase: $ git rebase --onto v1 f4d399238f bugfix/def

這很好用(在解決之后我必須在合並之前使用提交進行上游)。

如何合並提交之前找到兩個分支的共同祖先? (對於backport過程的第2步)。

試着

  1. git merge-base bugfix/abc master
    • 由於合並已經完成,因此只返回bugfix/abc頭部的提交
  2. 結合#1的結果,使用git log獲取此提交的子代

更新

這個問題和Find兩個分支的共同祖先之間的關鍵區別在於兩個分支已經合並。 正如我所提到的那樣, 最好的提交將作為合並分支的負責人返回。 我需要在合並提交之前使用共同的祖先。

假設bug修復后的分支並合並到master中,如下所示:

A---B v1
     \
      C---D---F---H master
           \     /
            E---G bugfix/abc

運行$ git merge-base master bugfix/abc將返回G但是我需要得到D (甚至F會為了使用rebase --onto )。

一旦我得到D,我就會跑:

$ git branch bugfix/def bugfix/abc
$ git rebase --onto v1 D bugfix/def
$ git checkout v1
$ git merge bugfix/def

最終得到了預期的結果:

      E'---G' bugfix/def
     /      \
A---B--------I v1
     \
      C---D---F---H master
           \     /
            E---G bugfix/abc

如何在合並提交之前找到兩個分支的共同祖先? (對於backport過程的第2步)。

有幾種選擇可供使用:

git merge-base

git merge-base是您要查找的命令

git merge-base在兩次提交之間找到最佳共同祖先,以便在三向合並中使用。 一個共同的祖先比另一個共同的祖先更好,如果后者是前者的祖先。 沒有任何更好的共同祖先的共同祖先是最好的共同祖先 ,即合並基礎 請注意,一對提交可以有多個合並基礎。

從日志中手動找到它

git log --decorate --graph --oneline --all

這將在日志中顯示叉點,以便您可以跟蹤分支的提交ID。

對於我所展示的情況,我找到了一個合理的解決方案:

git rev-list --first-parent master | gawk -v bugfix=bugfix/abc '{
    commit = $1
    branchCmd = "git branch --contains \"" commit "\" \"" bugfix "\""
    if (branchCmd | getline) {
        print commit
        exit
    }
}'

這將打印D

事實證明,如果master被合並到bugfix/abc ,則會失敗,如下所示:

      E'---G'---h' bugfix/def
     /           \
A---B-------------J v1
     \
      C---D---F-------I master
           \   \     /
            E---G---H bugfix/abc

在這種情況下,它將打印F但這仍然不是我們想要的。

如果只有branch --contains某些選項branch --contains來限制父母,例如--first-parent就像有rev-list ...

解決方法是將腳本修改為以下內容:

git rev-list --first-parent master | gawk -v bugfix=bugfix/abc '{
    commit = $1
    branchCmd = "git branch --contains \"" commit "\" \"" bugfix "\""
    if (branchCmd | getline) {
        timestampCmd = "git show -s --format=%ct \"" commit "\""
        if (timestampCmd | getline timestamp) {
            revlistCmd = "git rev-list --first-parent --max-age=" timestamp " \"" bugfix "\""
            while (revlistCmd | getline line) {
                if (commit == line) {
                    print commit
                    exit
                }
            }
        }
    }
}'

這里的想法是我們采取每個可能的結果並檢查是否可以從bugfix/abc到達,但只能跟隨第一個父進程。 --max-age意味着我們只會在必要時返回。 如果它不可達,則它必須是從masterbugfix/abc的合並。 如果是,那么我們打印提交哈希並退出。

暫無
暫無

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

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