5

私たちの Git プロセスでは、「マスター」は現在のリリース サイクルのトピックおよび修正ブランチの統合ブランチですが、マスターで既に正常にテストされた修正の一部を慎重にバックポートする必要がある「安定した」ブランチも維持しています。

すべての問題は、ブランチがすでに「マスター」にマージされていることです (そうでない場合は、リベース --onto を使用すると非常に簡単です)

  • 他の方法でプロセスを変更したくない理由は、a) "stable" ブランチのすべてを修正したくないため、b) "stable" ブランチに変更を加えなければならない場合があるからです。 「マスター」にマージしたい。
  • 明らかに、修正を「安定版」ブランチにマージすることはできません。これにより、多くの不要な機能がバックポートされるからです。

私が説明する初期状況のグラフ:

          I--J (stable)
         /
        /
       /
- A - B - C - D - E - F - G  (master) 
              \      /
               X -- Y (fix/123)

到達したい状況のグラフ:

          I--J (stable)
         /    \
        /      X'- Y' (fix/123-stable)
       /
- A - B - C - D - E - F - G  (master) 
              \      /
               X -- Y (fix/123)

修正を完了するための複数のマージなど、より複雑なケースも考えられます。

- A - B - C - D - E - F - G - H (master) 
               \     /       /
                X - Y ----- Z (fix/123)

ただし、修正ブランチへのマージは許可されていないため、次のようなものは決してありません。

- A - B - C - D - E - F - G (master) 
               \   \     /
                X - Y - Z (fix/123)

これを達成するために、修正ブランチをチェリーピックまたはリベースできます。

1)cherry-pick(通常、gitでコミットをバックポートするにはどうすればよいですか?):

git checkout -b fix/123-stable stable
git cherry-pick X Y

これは簡単に思えますが、実際の例を扱う場合はそうではありません。いくつかのコミットを忘れたり、間違ったコミットを選択したりするリスクは常にあります!

2) リベース --onto ( https://www.kernel.org/pub/software/scm/git/docs/git-rebase.html ) :

2.a) 「動かない」方法:

git rebase --onto stable master fix/123

fix/123 はすでに master にマージされているため、これは何もしません! 2.b)「チェリーピックよりもはるかに優れていない」方法:

git rebase --onto stable D fix/123

DのSHAを取得する必要があるため(たとえば、Xではなく)、これはまだ危険です。

2.c) 「一時的な開始参照を使用する」方法:

git tag begin D
git rebase --onto stable begin fix/123
git tag -d begin

これにより、以前の状況は改善されます。タグを使用すると、グラフィカル ツールで簡単に実行したりイメージしたりできるようになりますが、依然として多くの手作業が必要です。

3.d) 「マージ前にハード マスターをリセットする」(最初の分岐点まで) うーん、説明するのも実行するのも難しいようです。

したがって、私が探しているのは、git の移植可能な(bash/grep/cut/sed を暗示しない) 方法です。

1)すでに「マスター」にマージされたブランチ(ここではXとY、「マルチマージ」の場合はZ)で行われたすべてのコミットを一覧表示して、簡単にチェリーピックします

2) すでに「マスター」にマージされたブランチの最初のブランチ ポイントのコミットを取得する

2.a) マージは既に (複数回でも) 行われているため、「git merge-base」コマンドではこれを実行できません。

2.b) ここで見つけました Git で分岐点を見つけますか? 次の bash コマンドを少し調整しました。

git rev-list --boundary --date-order --reverse fix/123..master | grep -m 1 - | cut -c2-

しかし、彼はgit easyでも移植可能なコマンドでもありません(つまり、BashまたはCygwinツールなしでは機能しません)

4

2 に答える 2

6

記録のために、 「Gitで分岐点を見つける」に関するlindesの回答を指しているCraig Otisの回答に基づいて、最終的に使用している2つのソリューションを次に示します。 Ubuntu 12.10)

ブランチ "fix/123" が既に "master" にマージされている初期状態:

        I--J (stable)
       /
- A - B - C - D - E - F - G  (master) 
               \     /
                X - Y (fix/123)

1) "master" から始まる "fix/123" ブランチを "stable" にリベースするには (これは、これを読んでいるほとんどの人にとって一般的な答えです):

次の Bash エイリアスを「.gitconfig」ファイルに追加します。

[alias]
    oldest-ancestor = !bash -c 'diff -u <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | sed -ne \"s/^ //p\" | head -1' -
    rebase-onto     = !bash -c 'git rebase --onto $1 `git oldest-ancestor $2 $3` $3' -

次に、コマンド ラインを使用します。

git rebase-onto stable master fix/123

そして、ここにいます:

          I--J (stable)
         /    \
        /      X'- Y' (fix/123)
       /
- A - B - C - D - E - F - G  (master) 
               \     /
                X - Y

2)「master」から始まるブランチ「fix/123」をリベースするには、新しいブランチ「fix/123-stable」を「stable」に作成します(これは、私が使用するより具体的な答えです)。

次の Bash エイリアスを「.gitconfig」ファイルに追加します。

[alias]
    oldest-ancestor = !bash -c 'diff -u <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | sed -ne \"s/^ //p\" | head -1' -
    rebase-onto     = !bash -c 'git branch $4 $2 && git rebase --onto $3 `git oldest-ancestor $1 $4` $4' -

次に、コマンド ラインを使用します。

git rebase-onto master fix/123 stable fix/123-stable

そして、ここにいます:

          I--J (stable)
         /    \
        /      X'- Y' (fix/123-stable)
       /
- A - B - C - D - E - F - G  (master) 
               \     /
                X - Y (fix/123)
于 2013-05-23T16:11:04.287 に答える
4

私は Git にかなり慣れていないので、あなたの状況で私が誤解したかもしれないことをお許しください。

このコード スニペットの使用:

diff -u <(git rev-list --first-parent fix/123) <(git rev-list --first-parent master) | sed -ne 's/^ //p' | head -1

この回答から:「Gitで分岐点を見つける?」に対する@lindesの回答

次のようなツリーがある場合:

初期ツリー

次に、上記のコマンドの結果は次のようsome-fixfix/123なります。

f1efa4a9c029281a22d4fa8dd6607c523e7191f5

これは、最初の修正ブランチが作成されたコミットです。

次に、クイックを実行して、どこで終了merge-baseするかを判断することもできます。some-fix

$ git merge-base master some-fix
1b9ebb7157a958e9adc3b8eda9bf4175cd821c4b

そして、リビジョン範囲のチェリーピックを使用して、これらの変更を取り込むことができます:

$ git cherry-pick f1efa4a..1b9ebb7

そして、あなたは次のようになります:

最終木

これには、最初の修正ブランチからの追加のコミットが含まれています。に追加するのではなく、追加を実行してブランチcheckout -bを作成することをお勧めしますが、方法は同じである必要があります。fix/123-stablestable

私が参照した回答には、その長くて面倒なdiffコマンドを というエイリアスとしてインストールすることが記載されていることにも注意oldest-ancestorしてください。これにより、時間を大幅に節約できます。

于 2013-05-22T12:05:34.700 に答える