6

初期シナリオ:

A (master)
 \
 B - C  - D (development)

マージ後に欲しいもの --squash:

A     -     E (master/development)
 \         /
 B - C - D 

ブランチmastergit logは、

commit E
    Squashed commit of the following:
    commit D
    commit C
    commit B
commit A

ブランチで開発を続けるdevelopment:

A     -     E (master)
 \         / \         
 B - C - D    F - G - H (development)

再度スカッシュでマージします。

A     -     E     -     I(master/development)
 \         / \         /
 B - C - D    F - G - H

ブランチmastergit logは、

commit I
    Squashed commit of the following:
    commit H
    commit G
    commit F
commit E
    Squashed commit of the following:
    commit D
    commit C
    commit B
commit A

ブランチdevelopmentgit logは、

Commit I
Commit H
Commit G
Commit F
Commit E
Commit D
Commit C
Commit B
Commit A

masterすべてのコミットをオンに保ちながら、押しつぶされたコミットとマージしたいと思いdevelopmentます。

それを実装する方法がわかりません。私の問題は、最初のマージでDポイントを作成する方法がわからず、のみではなく含めることです。EIB,C,D,E,F,G,HF,G,H

4

3 に答える 3

4

あなたが示した構造では、あなたが望むログ結果を得ることができません(git log --merges master一種のことです)。必要なログを提供する構造は、ポイントを打ち負かします。そして、結局のところ、これは Git を操作する自滅的な方法です。


希望は、実行git log masterして、押しつぶされたコミットのみを表示できるようにすることです。これはうまくいきません。masterGit は、一部のコミットが を対象としており、一部が を対象としていることを認識していませんdevelopment。提案された構造を見てみましょう。

A     -     E     -     I [master] [development]
 \         / \         /
 B - C - D    F - G - H

この時点でmasterdevelopment同じコミットを指します。Git の歴史に関する限り、それらは同一です。ブランチは、コミットを指すラベルにすぎません。コミットは、コミットされたブランチを覚えていませんgit log masterAからgit log developmentI までのすべてのコミットを示す同じログが生成されます。 E および I の圧縮されたコミット ログは冗長になります。

(または) で必要なもの取得して、マージ コミットのみを表示できますが、 の一部として行われたものであっても、すべてのマージ コミット表示されます。だから、本当にうまくいきません。git log --merges masterdevelopmentdevelopment

このアイデア全体は不必要に複雑です。読み進めてください。


必要なログ結果を得るには、このように 2 つのブランチ間の関係を壊す必要があります。

A     -     E     -     I [master]
 \                   
 B - C - D - F - G - H [development]

何とか機能させることはできますが、意味がありません。 git log masterにはすべて同じログ メッセージが含まれているため、 と同じくらい長くなりgit log developmentますが、それらは一緒に粉砕されます。git log master変更がすべて 1 つの diff にまとめられて、変更行を特定のコミット メッセージに関連付けるのが難しくなるため、コード考古学 (つまり、「この行はこのように書かれた理由」) を行うために使用することはできません。masterとの履歴developmentは関連付けられていないため、開発中のすべてを確実にマスターにする方法、またはその逆 (マスターへのホット フィックスなど) を保証する方法はありません。

git log masterよりも情報が少なくgit log development、理解が困難です。masterマージ履歴との関連性がなくdevelopment、保持するすべての利点が失われます。この複雑な設定を維持しても意味がありません。


代わりに、機能ブランチ (1 つの継続的な「開発」ブランチではなく)git merge --no-ffをマージし、考古学を容易にするためにブランチ履歴を保持するために使用します。

              G - J [feature/tacos]
             /
A     -     E     -     K [master]
 \         / \         /
 B - C - D    F - H - I

E と K は、 によって生成される通常のマージ コミットgit merge --no-ffです。development機能ブランチによって処理される連続ブランチはありません。フィーチャー ブランチは使い捨てであり、マージされると削除されます。フィーチャー ブランチに関する情報はマージ コミットに保持さgit merge --no-ffれ、ブランチ構造が保持されることが保証されます。feature/tacosまだマージされていないタコスで動作する機能ブランチです。

git log --graph --decorate mastermaster の完全な履歴が表示され、機能がいつ終了したかを示すマージ コミットと、ブランチの履歴を示す行が表示されます。GitXなどの GUI Git 履歴ツールは、履歴をグラフとして読み取るもう 1 つの方法です。

最後に、Git の履歴はグラフです。そのグラフの操作方法を学べば、Git での生活がずっと楽になります。大量のパンケーキのように、Git の履歴を直線的にしようとすると、Git の要点が失われ、自分自身と他のすべての人のために余分な作業が発生します。

于 2015-10-17T21:53:21.573 に答える
1

ブランチをマージすると、いずれにせよコミット ログに両方のブランチからのコミットが表示されるため、求めているものを正確に取得することは不可能です。あなたが望むかもしれないのはそのようなものです:

A      -     E (master)
 \         
 B - C - D (development)

developmentブランチからコミットをチェリーピックし、それらを押しつぶして、上に適用するだけですmaster

これを取得する最も簡単な方法は、次のようなものです。

git checkout development && git rebase -i master HEAD

次に、最初のアクションを除くすべてのアクションを に置き換えますsquash。その結果、押しつぶされたコミットを指す切り離されたヘッドが得られ、 の上に適用されmasterます。masterこのコミットにリセットするだけで完了です。

コミットメッセージは、ハッシュではなくすべてのコミットのコミットメッセージを再保存するため、正確にはあなたが望むものではないと思いますが、--execオプションを使用してコミットメッセージ生成にフックすることができます。

すべてが少し手動ですが、すべてをスクリプト化してエイリアスを作成できます。git上位レベルのプログラミング言語ですべてを書き直すのではなく、それ自体を使用して得ることができる最も近い方法だと思います。

于 2015-10-17T22:15:26.307 に答える
0

それは単なる通常のマージです...

#!/bin/sh
git init
touch a; git add a; git commit -m a
git checkout -b patch
touch b; git add b; git commit -m b
touch c; git add c; git commit -m c
git checkout master
git merge --no-ff patch
git log --graph --oneline

結果

*   a9fbaec Merge branch 'patch'
|\
| * fb7eac4 c
| * 94f44c1 b
|/
* 4de57a5 a
于 2015-10-17T21:03:12.003 に答える