コミットされた後、gitでコミットをスカッシュする方法は?


550

これは、複数のコミットを押しつぶすことの良い説明になります:

http://git-scm.com/book/en/Git-Branching-Rebasing

ただし、すでにプッシュされているコミットには機能しません。ローカルリポジトリとリモートリポジトリの両方で、最新のいくつかのコミットをどのように押しつぶすのですか?

編集:私が行うときgit rebase -i origin/master~4 master、最初の1つをに保ち、pick他の3 つをに設定してから、squash(emacsのcx ccを介して)終了します:

$ git rebase -i origin/master~4 master
# Not currently on any branch.
nothing to commit (working directory clean)

Could not apply 2f40e2c... Revert "issue 4427: bpf device permission change option added"
$ git rebase -i origin/master~4 master
Interactive rebase already started

ここで、2f40はpickコミットです。そして、4つのコミットはどれもに表示されませんgit log。コミットメッセージを入力できるように、エディターを再起動することを期待していました。何が悪いのですか?

回答:


780

Squashはローカルでコミットします

git rebase -i origin/master~4 master

そして、プッシュを強制します

git push origin +master

--force+

のドキュメントからgit push

--forceは、プッシュされるすべての参照に適用されることに注意してください。したがって、それをpush.defaultset to matchingまたは複数のプッシュ宛先で構成して使用するとremote.*.push、現在のブランチ以外の参照が上書きされる可能性があります(リモートの相手の背後にあるローカル参照を含む)。プッシュを1つのブランチのみに強制するに+ は、refspecの前にあるプッシュを使用して(たとえばgit push origin +mastermasterブランチにプッシュを強制的に)します。


30
次のこともできますgit push --force origin master
Daenyth

7
Daenyth:はい。ただし、この構文は短いため、常にこの構文を使用します。
Alavi

86
そしてもちろん、他の誰かがリモートリポジトリからプルした可能性がある場合、おそらくこれを行いたくないでしょう。その場合の答えは「そうしない」です。
Cascabel

10
また、OPはコマンドを正確にコピーしていると思います。git rebase -i origin/master実際には、それよりもずっと前にコミットをリベースする方法を知りたいと思っていますgit rebase -i origin/master~20 master
Cascabel

6
gstackoverflow+接頭辞が付いたrefspecのみを強制します。--forceプッシュされるすべての参照仕様を強制します。更新された回答をご覧ください。
アランハガイAlavi 2014

120

ブランチでは、このようにすることができました(最後の4つのコミット)

git checkout my_branch
git reset --soft HEAD~4
git commit
git push --force origin my_branch

1
すでにプッシュされたブランチでソフトコマンドを使用してこれを行うと、他の多くの人々のコミットをプッシュしてしまいました。
チェンバレン

3
トン?どうすれば4を超えることができますか?詳しく説明できますか?
jakob-r 2016

それは私にはわかりませんが、すでにプッシュされたコミットを押しつぶそうとすることと関係がありました。-他の人のように見えますが、ここで同様の経験stackoverflow.com/questions/5189560/...
cchamberlain

4
私はこれを期待される答えとして受け入れたでしょう。答えを受け入れたよりきれいな。
vikramvi 2016

4
これは、たった4つのステップで最も明確で受け入れられている答えです
アメヤサラグレ

45

受け入れられた回答との小さな違いですが、私はつぶすのに多くの困難を抱えていて、最終的にそれを得ました。

$ git rebase -i HEAD~4
  • 開いたインタラクティブ画面で、スカッシュ したいすべてのコミットのpickを上部のsquashに置き換えます。
  • エディタを保存して閉じます esc --> :wq

以下を使用してリモートにプッシュします。

$ git push origin branch-name --force

2
簡潔で効果的、詳細:
terwxqian

22

多くの問題は、のみ作成することによって回避することが可能branchに&動作するようではないに取り組んでmaster

git checkout -b mybranch

以下は、remoteすでにプッシュさremoteれたコミットとプッシュされたコミットの混合/ localコミットのみの場合に機能します。

# example merging 4 commits

git checkout mybranch
git rebase -i mybranch~4 mybranch

# at the interactive screen
# choose fixup for commit: 2 / 3 / 4

git push -u origin +mybranch

また、プルリクエストのメモもいくつか参考になります。


17

git rebase -i master

エディターvmが開き、次のようなメッセージが表示されます

Pick 2994283490 commit msg1
f 7994283490 commit msg2
f 4654283490 commit msg3
f 5694283490 commit msg4
#Some message 
#
#some more

ここで、他のすべてのコミットのピックを「f」(フィックスアップの略)に変更しました。

git push -f origin feature/feature-branch-name-xyz

これにより、すべてのコミットが1つのコミットに修正され、他のすべてのコミットが削除されます。私はこれをしました、そしてそれは私を助けました。


3

GitlabまたはGithubを使用している場合、この方法で問題が発生する可能性があります。上記の方法のいずれかを使用してコミットをスカッシュします。私の好きなものは:

git rebase -i HEAD~4
or
git rebase -i origin/master

コミットするためにスカッシュまたはフィックスアップを選択します。この時点で、gitステータスを確認します。そしてメッセージは次のようになります:

    On branch ABC-1916-remote
    Your branch and 'origin/ABC-1916' have diverged,
    and have 1 and 7 different commits each, respectively.
      (use "git pull" to merge the remote branch into yours)

そして、あなたはそれを引っ張りたくなるかもしれません。そうしないと、以前と同じ状況になります。

代わりに、次のコマンドでオリジンにプッシュします。

git push origin +ABC-1916-remote:ABC-1916

+を使用すると、1つのブランチのみに強制的にプッシュできます。


プルに問題はありません。特に、競合がある場合は、プッシュを強制するよりも簡単に解決できます
Ray_Poly

2

1つのブランチで2つのコミット(そのうちの1つはすでにプッシュされています)を押しつぶすために、以下が機能しました:

git rebase -i HEAD~2
    [ pick     older-commit  ]
    [ squash   newest-commit ]
git push --force

デフォルトでは、これには最新のコミットのコミットメッセージが古いコミットのコメントとして含まれます。


2

1) git rebase -i HEAD~4

詳しく説明すると、現在のブランチで機能します。HEAD〜4は、最新の4つのコミットを押しつぶすことを意味します。対話モード(-i)

2)この時点で、エディターはコミットのリストを使用して開き、2番目以降のコミットを変更します。ピックをスカッシュに置き換えて保存します。

出力:refs / heads / branch-nameが正常にリベースおよび更新されました。

3) git push origin refs/heads/branch-name --force

出力:

remote:
remote: To create a merge request for branch-name, visit:
remote: http://xxx/sc/server/merge_requests/new?merge_request%5Bsource_branch%5D=sss
remote:To ip:sc/server.git
 + 84b4b60...5045693 branch-name -> branch-name (forced update)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.