git format-patchを使用して、コミットを1つのパッチにまとめる方法を教えてください。


163

ブランチで8つのコミットを取得しましたが、まだgitに対応していない人にメールを送りたいと思っています。これまでのところ、私が行うすべてのことで、8つのパッチファイルが提供されるか、ブランチの履歴にあるコミットごとに、最初からパッチファイルが提供されるようになります。私はgit rebase --interactiveを使用してコミットを押しつぶしましたが、今や私が試みるすべてのものは、最初から何十億ものパッチを与えてくれます。何が悪いのですか?

git format-patch master HEAD # yields zillions of patches, even though there's 
                             # only one commit since master

以下の命題のなかで、どの方法を使用するのか興味があります。お知らせください;)
VonC 2009年

4
Rob Di Marcoの提案に従って、git diffを使用します。しかし、私は2週間仕事を休んでいて、昨晩2番目の女の赤ちゃんの誕生を目撃したばかりなので、それを使用するまでにはしばらくかかります。:)
skiphoppy 2009年

2
git format-patch --squash master HEAD
schoetbi

1
回転範囲を指定するには、master..HEADを試してください。
Konrad Kleine 2014

回答:


186

次のように使い捨てブランチでこれを行うことをお勧めします。コミットが「newlines」ブランチにあり、すでに「master」ブランチに戻っている場合、これでうまくいくはずです。

[adam@mbp2600 example (master)]$ git checkout -b tmpsquash
Switched to a new branch "tmpsquash"

[adam@mbp2600 example (tmpsquash)]$ git merge --squash newlines
Updating 4d2de39..b6768b2
Fast forward
Squash commit -- not updating HEAD
 test.txt |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

[adam@mbp2600 example (tmpsquash)]$ git commit -a -m "My squashed commits"
[tmpsquash]: created 75b0a89: "My squashed commits"
 1 files changed, 2 insertions(+), 0 deletions(-)

[adam@mbp2600 example (tmpsquash)]$ git format-patch master
0001-My-squashed-commits.patch

お役に立てれば!


2
これは、ローカルで履歴を保持したいときに使用します(パッチを編集する必要がある場合)。それ以外の場合は、rebase -iを使用してコミットを押しつぶすだけです。
2009年

5
私にとっては、git comit -m "My squashed commits"他の方法で追跡することで信頼性が向上しました。追跡されていない他のファイルが追加されます
Sebastian

コミットからAdditonally、あなたがコミットする代わりに、マスターのコミット特定に切り替えて、パッチを作成するには、この操作を行うことができますgit checkout 775ec2a && git checkout -b patch && git merge --squash branchname
ベリーM.

131

ポットにもう1つのソリューションを追加するだけです。代わりにこれを使用する場合:

git format-patch master --stdout > my_new_patch.diff

次に、それはまだ8つのパッチになります...しかし、それらはすべて単一のパッチファイルに含まれ、次のように1つとして適用されます。

git am < my_new_patch.diff

13
私はこのソリューションが好きです。@Adam Alexanderが説明した方法よりもはるかに大きなパッチが作成される場合があることに注意してください。これは、コミットによって複数のファイルが編集される可能性があるためです。このメソッドは、一部のファイルが元に戻された場合でも、各コミットを個別に処理します。しかし、ほとんどの場合、これは問題ではありません。
gumik

1
このオプションは、マージを避けたい場合に最適です。(例えば、いくつかのコミットをスキップしたい)。あなたはまだgit rebase -i ...それらをすべて1つに押しつぶすことができます。
ホルヘオルピネル2017年

21

私はいつもgit diffを使っているので、あなたの例では、

git diff master > patch.txt

15
すべてのコミットメッセージとメタデータが失われる場合を除きます。git format-patchの優れた点は、一連のパッチからブランチ全体を再構築できることです。
mcepl 2011

create-branch-and-squashメソッドには、すべてのコミットメッセージを1つにまとめるという利点がありますが、独自のコミットメッセージを記述したい場合は、この方法の方がはるかに高速です
woojoo666

実際、結合されたメッセージはを使用して行うことができます。例git logについては私の回答を参照しください
woojoo666

2
いいオプションですが、 'git diff'にはバイナリ差分を含めることができないことを考慮してください(多分それを行うオプションがあるかもしれません)。
サンティアゴヴィラフエルテ2016

18

これは、変更がマスターブランチにある場合のAdam Alexander回答の適応です。これは次のことを行います:

  • 必要なポイントから新しい使い捨てブランチ「tmpsquash」を作成します(「git --log」を実行している、またはgitgを実行しているSHAキーを探します。tmpsquashヘッドにしたいコミットを選択します。マスター内のその後のコミットは押しつぶされたコミット)。
  • マスターからtmpsquashへの変更をマージします。
  • 押し潰された変更をtmpsquashにコミットします。
  • 押しつぶされたコミットでパッチを作成します。
  • マスターブランチに戻ります

laura@rune:~/example (master)$ git branch tmpsquash ba3c498878054e25afc5e22e207d62eb40ff1f38
laura@rune:~/example (master)$ git checkout tmpsquash
Switched to branch 'tmpsquash'
laura@rune:~/example (tmpsquash)$ git merge --squash master
Updating ba3c498..40386b8
Fast-forward
Squash commit -- not updating HEAD

[snip, changed files]

11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example  (tmpsquash)$ git commit -a -m "My squashed commits"
[test2 6127e5c] My squashed commits
11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example  (tmpsquash)$ git format-patch master
0001-My-squashed-commits.patch
laura@rune:~/example  (tmpsquash)$ git checkout master
Switched to branch 'master'
laura@rune:~/example  (master)$

masterで変更を加えることは、自分でリモートにプッシュしない場合のアンチパターンです。そしてもしそうなら、おそらくそれらのためのパッチファイルを生成する必要はありません。
ivan_pozdeev

18

ご存知のとおり、a git format-patch -8 HEADは8つのパッチを提供します。

8つのコミットを1つにまとめたい場合、ブランチの履歴を書き直してもかまいません(o-o-X-A-B-C-D-E-F-G-H)、次のようにできます。

git rebase -i
// squash A, B, C, D, E ,F, G into H

または、それがより良い解決策となる場合は、8つのすべてのコミット8つのコミットの前のコミット)を新しいブランチ再生します。X

git branch delivery X
git checkout delivery
git merge --squash master
git format-patch HEAD

そうすれば、「delivery」ブランチにコミットが1つだけあり、それが最後の8つのコミットすべてを表します


git merge master単に早送りを行い、コミットを1つに押しつぶすことはありません。に変更するgit merge --squash masterと、すべてのコミットが抑制され、ステージングされた領域に表示されます。フローはこの変更で機能します。(私はgitバージョン2.1.0を使用しています。)
Stunner '13年

5

2つのタグ間のフォーマットパッチ:

git checkout <source-tag>
git checkout -b <tmpsquash>
git merge --squash <target-tag>
git commit -a -m "<message>"
git format-patch <source-tag>

5

最も簡単な方法は、を使用し、スカッシュメソッドが出力するコミットメッセージを組み合わせたい場合にgit diff追加git logすることです。たとえば、コミットabcdと次の間にパッチを作成するには1234

git diff abcd..1234 > patch.diff
git log abcd..1234 > patchmsg.txt

次に、パッチを適用するとき:

git apply patch.diff
git add -A
git reset patch.diff patchmsg.txt
git commit -F patchmsg.txt

非テキストファイル(画像や動画など)を扱う場合は、への--binary引数を忘れないでくださいgit diff


0

アダムアレクサンダーの答えに基づいて:

git checkout newlines
## must be rebased to master
git checkout -b temporary
# squash the commits
git rebase -i master
git format-patch master
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.