Gitリポジトリの最初の2つのコミットを結合しますか?


197

3つのコミットA、BCを含む履歴があるとします。

A-B-C

2つのコミットABを1つのコミットABに結合したいと思います。

AB-C

私は試した

git rebase -i A

次の内容でエディターが開きます。

pick e97a17b B
pick asd314f C

これを次のように変更します

squash e97a17b B
pick asd314f C

それからGit 1.6.0.4は言う:

Cannot 'squash' without a previous commit

方法はありますか、これは単に不可能ですか?



回答:


168

git rebase -i --root Git バージョン1.7.12以降で使用してください。

インタラクティブなリベースファイルで、コミットBの 2行目をスカッシュに変更し、他の行はpickのままにしておきます。

pick f4202da A
squash bea708e B
pick a8c6abc C

これにより、2つのコミットABが1つのコミットABに結合されます。

この回答で見つかりました。


126

あなたがしようとした:

git rebase -i A

以下ではeditなく続行すると、そのように開始できますsquash

edit e97a17b B
pick asd314f C

次に実行します

git reset --soft HEAD^
git commit --amend
git rebase --continue

できました。


4
github gistを静かに修正するためにこれを行っている場合は、コミットに-m "initial"を追加する必要があります。;-)
Bruno Bronosky

1
git rebase --abort最初からやり直して正しい方法で(エディタで最初のコミットを押しつぶさないように)
oma

66

A最初のコミットでしたが、今あなたBは最初のコミットになりたいです。git commitはツリー全体であり、導入されたdiffの観点から通常説明および表示されている場合でも、diffではありません。

このレシピは、AとB、およびBとCの間に複数のコミットがある場合でも機能します。

# Go back to the last commit that we want
# to form the initial commit (detach HEAD)
git checkout <sha1_for_B>

# reset the branch pointer to the initial commit,
# but leaving the index and working tree intact.
git reset --soft <sha1_for_A>

# amend the initial tree using the tree from 'B'
git commit --amend

# temporarily tag this new initial commit
# (or you could remember the new commit sha1 manually)
git tag tmp

# go back to the original branch (assume master for this example)
git checkout master

# Replay all the commits after B onto the new initial commit
git rebase --onto tmp <sha1_for_B>

# remove the temporary tag
git tag -d tmp

1
これを実行すると、大規模なインタラクティブリベースがトリガーされますgit rebase --onto tmp <sha1_for_B>
Alex

私がたった2つのコミット(1つにまとめたい)の真新しいリポジトリがあることを考えると、これは私にとって完璧に機能しました。ありがとう@CBベイリー
RominRonin

10

インタラクティブなリベースの場合、リストが次のようになるようにAの前に行う必要があります。

pick A
pick B
pick C

になる:

pick A
squash B
pick C

Aが初期コミットである場合、Aの前に別の初期コミットを行う必要があります。Gitは違いを考慮し、(AとB)と(BとC)の違いを処理します。したがって、スカッシュはあなたの例では機能しません。


9

数百または数千のコミットがある場合は、コストモの回答を使用して

git rebase -i --root

リベーススクリプトが2回処理しなければならない多数のコミット、1回はインタラクティブなリベースエディターリストを生成するために(各コミットに対して実行するアクションを選択する)、1回は実際にコミットの再適用。

これは、そもそもインタラクティブリベースを使用しないことでインタラクティブリベースエディターリストを生成する時間コストを回避する代替ソリューションです。このように、これはCharles Baileyのソリューションに似ています。2番目のコミットから孤立ブランチを作成し、その上にすべての子孫コミットをリベースするだけです。

git checkout --orphan orphan <second-commit-sha>
git commit -m "Enter a commit message for the new root commit"
git rebase --onto orphan <second-commit-sha> master

ドキュメンテーション



0

分隊のGitコマンド:git rebase -i HEAD〜[コミット数]

以下のgitコミット履歴があるとします。


pick 5152061 feat:画像保存のサポートを追加しました。(A)
ピック39c5a04修正:バグ修正。(B)
839c6b3修正を選択:競合を解決しました。(C)

AとBをABに押しつぶしたい場合は、以下の手順を実行します。


pick 5152061 feat:画像保存のサポートを追加しました。(A)
s 39c5a04修正:バグ修正。(B)
839c6b3修正を選択:競合を解決しました。(C)

注:squashing commitの場合、squashまたはsを使用できます。最終結果は次のようになります
。pick 5152061 feat:画像の保存のサポートが追加されました。(AB)
839c6b3修正を選択:競合を解決しました。(C)


-1

コマンドラインの魔法を少し実行する必要があります。

git checkout -b a A
git checkout B <files>
git commit --amend
git checkout master
git rebase a

これで、ABとCがコミットされているブランチが残ります。


新旧の初期コミットには共通の祖先がないため、gitがマスターに履歴をすべて適用しようとすると、ツリーが共通であっても不要な競合が発生する可能性があります。--ontoオプションを使用してgit rebaseを実行すると、gitに適用を開始する正しい場所を指示できます。
CBベイリー、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.