Git:ブランチですべてのコミットを押しつぶす方法


315

私はからブランチを新しくmasterします:

git checkout -b testbranch

私はそれに20回コミットします。

今、私はそれらの20のコミットを押しつぶしたいと思います。私はそれをします:

git rebase -i HEAD~20

コミット数がわからない場合はどうなりますか?次のようなことをする方法はありますか?

git rebase -i all on this branch

6
git rebase -i 58333012713fc168bd70ad00d191b3bdc601fa2dcommitnumberが変更されない
拒否

最後にこの方法を使用する@dennsは、あなたがリベースされているブランチにコミットから幻想的に働きました。本当にありがとう!
Joshua Pinter

回答:


395

すべてのコミットを押しつぶすもう1つの方法は、インデックスをマスターにリセットすることです。

 git checkout yourBranch
 git reset $(git merge-base master yourBranch)
 git add -A
 git commit -m "one commit on yourBranch"

これは、「yourBranch」がどのブランチからのものかを知っていることを意味するため、完全ではありません。
注:Gitでoriginブランチを見つけるのは簡単ではありません(ここで見られるように多くの場合、視覚的な方法が最も簡単です)。


編集:使用する必要があります git push --force


Karlotcha Hoaコメントに追加しました

リセットについては、

git reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD)) 

[それ]は、現在いるブランチを自動的に使用します。
あなたはそれを使用する場合と、コマンドは支店名に依存しないよう、あなたはまた、別名を使用することができます


2
YourBranch現在の場所をコミットするためにチェックアウトする方が良いです。これを行ってYourBranchも問題はありませんreset
Eugen Konkov

1
@Abdurrahimまたはgit bashを開くと、thosコマンドをコピーして貼り付けることができます!
VonC

3
リセットgit reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD))するには、現在使用しているブランチを自動的に使用するようにできます。コマンドをブランチ名に依存しないため、これを使用する場合はエイリアスも使用できます。
Karlotcha Hoa

1
@Druska simlpe分岐の場合、いいえ、正常に動作するはずです。
VonC 2018

1
@Shimmyはい、リセット後に強制的にプッシュしたgit push --force場合(およびそのブランチで作業している複数の人がいる場合は同僚に警告します)
VonC

112

すべてのコミットを1つのコミットに圧縮するブランチをチェックアウトします。その呼び出されたとしましょう、feature_branch

git checkout feature_branch

ステップ1:

origin/feature_branchローカルmasterブランチでをソフトリセットします(必要に応じて、オリジン/マスターでもリセットできます)。これにより、のすべての追加コミットがリセットされますfeature_branchが、ファイルの変更はローカルで変更されません。

git reset --soft master

ステップ2:

作成する新しいコミットに、git repoディレクトリのすべての変更を追加します。同じことをメッセージでコミットします。

git add -A && git commit -m "commit message goes here"


6
これは私にとって最も信頼できる解決策でした。リベースエラーやマージの競合を引き起こさなかったのです。
アンタラ

1
警告:git add -Aローカルフォルダーにあるすべてのものをブランチに追加します。
デビッドH

このソリューションが大好きです!これがまさに私が欲しかったものです!
jacoballenwood

1
noobの最善の解決策-非破壊的でおっとっとする瞬間は、アプリのシークレットなどのチェックインが多すぎる可能性があります。適切なgitignoreファイルがある場合は問題ありません
kkarakk

@NSduToit短い答え:いいえ、必要はありません。私の回答で上記の手順を実行した後、コードが変更された1つのコミットが作成されます。コードを変更した他のコミットと同じように考えることができます。-fフラグなしでそれをリモートブランチにプッシュできます。
シャンキー

110

あなたがやっていることはかなりエラーが発生しやすいです。ただやる:

git rebase -i master

これにより、ブランチのコミットのみが現在の最新のマスターに自動的にリベースされます。


5
おかげで、私はそれを手に入れましたが、なぜシステムエラーが発生しやすいのですか
user3803850

10
おそらく数を間違えやすいからでしょうか?
ダニエルスコット

13
これがあなたの最善の解決策であることに同意しました。しかし、あなたがする必要があることをよりよく説明しているので、このリンクをたどってください。
Christo

3
コミットを押しつぶす代わりに、ブランチをマスターにマージして、gitをorigin / masterにリセットして、すべてのコミットのステージングを解除できます。これにより、既存のcommit -am "the whole thing!"
ステージングされてい

2
@nurettin reset origin/masterマスターで直接コミットするのと同じ方法なので、メソッドは本当に悪いと思います-「ブランチのマージ」履歴がなく、プルリクエストオプションがありません。@WaZaAの答えは、私が思う通常のgitワークフローにはるかに一致している
Drenai

79

これを行う別の簡単な方法:originブランチに行き、を実行しmerge --squashます。このコマンドは「押しつぶされた」コミットを行いません。これを行うと、yourBranchのすべてのコミットメッセージが収集されます。

$ git checkout master
$ git merge --squash yourBranch
$ git commit # all commit messages of yourBranch in one, really useful
 > [status 5007e77] Squashed commit of the following: ...


1
これは、親ブランチにスカッシュしたくない場合に機能します。親ブランチに基づいて新しいブランチを作成して切り替え、スカッシュマージをそれに実行します。
シャーロット

乾杯の仲間、素晴らしいヒント!
Nestor Milyaev

いいね!最初に「マスター」から「temp」ブランチを作成して「yourBranch」を押しつぶし、次に「temp」を「master」にマージします。
lazieburd

34

マスターから分岐していると仮定すると、yourBranch常にリセットステップに入る必要はありません。

git checkout yourBranch
git reset --soft HEAD~$(git rev-list --count HEAD ^master)
git add -A
git commit -m "one commit on yourBranch"

説明

  • git rev-list --count HEAD ^masterマスターf.exから機能ブランチを作成してからのコミットをカウントします。20。
  • git reset --soft HEAD~20最後の20回のコミットをソフトリセットします。これにより、変更がファイルに残りますが、コミットは削除されます。

使用法

私の.bash_profileにgisquash、1つのコマンドでこれを行うためのエイリアスを追加しました。

# squash all commits into one
alias gisquash='git reset --soft HEAD~$(git rev-list --count HEAD ^master)'

リセットしてコミットした後、を実行する必要がありますgit push --force

ヒント

Gitlab> = 11.0を使用している場合、ブランチをマージするときにスカッシュオプションがあるため、これを行う必要はありません 。 Gitlabスカッシングオプション


15

Stackoverflowのいくつかの質問とスカッシュに関する回答を読んだことに基づいて、これはブランチのすべてのコミットをスカッシュするための良い1つのライナーだと思います:

git reset --soft $(git merge-base master YOUR_BRANCH) && git commit -am "YOUR COMMIT MESSAGE" && git rebase -i master

これは、マスターがベースブランチであると想定しています。


1
おかげで、会社は多くの制限を設けており、保存して声を出さなかったため、エディターで通常の方法でリベースすることができませんでした。このブランチはマージのためにLead devに行き、彼はそれが好きではないため、gitでスカッシュとマージ機能を使用することもできませんでした。この1つのライナーが機能し、頭痛の種を救いました。素晴らしい仕事。
L1ghtk3ira 2017年

10

クリックを好む人のためのソリューション:

  1. sourcetreeをインストールする(無料)

  2. コミットの様子を確認してください。おそらくあなたはこれに似たものを持っています ここに画像の説明を入力してください

  3. コミットを右クリックします。私たちの場合、それはマスターブランチです。

ここに画像の説明を入力してください

  1. ボタンをクリックすることで、コミットを以前のものとつぶすことができます。この例では、2回クリックする必要があります。コミットメッセージを変更することもできます ここに画像の説明を入力してください

  2. 結果は素晴らしいです、そして私たちはプッシュする準備ができています! ここに画像の説明を入力してください

補足:部分的なコミットをリモートにプッシュする場合、スカッシュ後に強制プッシュを使用する必要があります


これをありがとう!
クリスタル

0

別の解決策は、すべてのコミットログをファイルに保存することです

git log> branch.log

これで、branch.logには最初からすべてのコミットIDが含まれています。下にスクロールして、最初のコミットを使用して最初のコミット(ターミナルでは難しい)を取得します。

git reset --soft

すべてのコミットが押しつぶされます


0

以前の多くの回答で述べたように、Gitリセットは、あなたが望むものを達成するための最善かつ最も簡単な方法です。次のワークフローで使用します。

(開発ブランチ上)

git fetch
git merge origin/master  #so development branch has all current changes from master
git reset origin/master  #will show all changes from development branch to master as unstaged
git gui # do a final review, stage all changes you really want
git commit # all changes in a single commit
git branch -f master #update local master branch
git push origin master #push it

0

このgitリセット、ハード、ソフト、およびここで説明されている他のすべては、手順を正しく実行し、ある種のジニーを実行すれば、おそらく機能しています(私にとってはうまくいきませんでした)。
あなたが平均的なジョーのsmoであるなら、これを試してください:
git merge --squashの使用方法?


私の人生を救った、そしてスカッシュに行くつもりだ、私はそれを知ってからこれを4回使ってきた。シンプルでクリーン、基本的には1つのコマンド。簡単


に言うと、ブランチを使用している場合は、「my_new_feature」を開発オフにして、プルリクエストに35回(またはいくつ)コミットして、1にしたい場合があります

。A.ブランチが最新であることを確認してください。 「my_new_feature」との競合を開発、最新化し、マージして解決します
(このステップは、とにかくいつでもできるだけ早く実行する必要があります)

B.最新の開発を取得し、「my_new_feature_squashed」という新しいブランチに分岐します。

C. 魔法はここにあります。
作業を "my_new_feature"から "my_new_feature_squashed"に変更したい場合は、次のようにしてください
(開発から作成した新しいブランチで):
git merge --squash my_new_feature

これで、すべての変更が新しいブランチに反映されるので、自由にテストしてから、そのブランチの1つのコミット、プッシュ、新しいPRを実行し、翌日繰り返されるのを待ちます。
コーディングが好きではないですか?:)


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.