私はgit内のリベース機能全体に少し慣れていません。次のコミットを行ったとしましょう。
A -> B -> C -> D
その後、にD
追加されたいくつかの新しいコードに依存する修正が含まれているA
こと、およびこれらのコミットが一緒に属していることに気付きました。どうすれば押しつぶしA
てD
一緒に、離れて一人でいることができB
ますC
か?
私はgit内のリベース機能全体に少し慣れていません。次のコミットを行ったとしましょう。
A -> B -> C -> D
その後、にD
追加されたいくつかの新しいコードに依存する修正が含まれているA
こと、およびこれらのコミットが一緒に属していることに気付きました。どうすれば押しつぶしA
てD
一緒に、離れて一人でいることができB
ますC
か?
Bの前にDを実行git rebase --interactive
して並べ替え、DをAに押しつぶすことができます。
Gitがエディターを開き、次のようなファイルが表示されます。例:git rebase --interactive HEAD~4
pick aaaaaaa Commit A
pick bbbbbbb Commit B
pick ccccccc Commit C
pick ddddddd Commit D
# Rebase aaaaaaa..ddddddd onto 1234567 (4 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
次に、次のように見えるファイルを変更します。
pick aaaaaaa Commit A
squash ddddddd Commit D
pick bbbbbbb Commit B
pick ccccccc Commit C
そして、gitはAとDの変更を1つのコミットにマージし、後でBとCを配置します。Dのコミットメッセージを保持したくない場合は、の代わりにキーワードsquash
を使用します。fixup
詳細については、ドキュメントfixup
を参照するか、いくつかの良い答えがあるこの質問をチェックしてください。git rebase
注:結果が分からない限り、別のリポジトリにプッシュされたコミットを変更しないでください。
git log --oneline -4
D commit_message_for_D
C commit_message_for_C
B commit_message_for_B
A commit_message_for_A
git rebase --interactive
pick D commit_message_for_D
pick C commit_message_for_C
pick B commit_message_for_B
pick A commit_message_for_A
タイプi
(VIM を挿入モードにする)
リストを次のように変更します (コミット メッセージを削除または含める必要はありません)。つづりを間違えないでくださいsquash
!:
pick C commit_message_for_C
pick B commit_message_for_B
pick A commit_message_for_A
squash D
Esc次に入力しZZ
ます(保存してVIMを終了します)
# This is a combination of 2 commits.
# The first commit's message is:
commit_message_for_D
# This is the 2nd commit message:
commit_message_for_A
タイプi
テキストを、新しいコミット メッセージの外観に変更します。commitA
との変更点を説明することをお勧めしD
ます。
new_commit_message_for_A_and_D
入力EscしてからZZ
git log --oneline -4
E new_commit_message_for_A_and_D
C commit_message_for_C
B commit_message_for_B
git show E
(You should see a diff showing a combination of changes from A and D)
これで、新しい commit が作成されましたE
。コミットA
しD
て、履歴にはもうありませんが、消えていません。この時点でまだそれらを復元できますが、しばらくの間はgit rebase --hard D
(によってgit rebase --hard
ローカルの変更が破棄されます! )。
SourceTreeを使用している場合:
まだコミットをプッシュしていないことを確認してください。
Squash with previous
インタラクティブなリベースは、20 ~ 30 個のコミットを含む大きな機能ブランチが作成されるまで、および/またはマスターからのマージがいくつか行われるまで、またはブランチでコミットしている間に競合が修正されるまではうまく機能します。履歴からコミットを見つけて置き換えても、ここでは機能pick
しsquash
ません。だから私は別の方法を探していて、この記事を見つけました。別のブランチでこれを機能させるために変更を加えました。
git checkout master
git fetch
git pull
git merge branch-name
git reset origin/master
git branch -D branch-name
git checkout -b branch-name
git add --all
#Do some commit
git push -f --set-upstream origin branch-name
この前に、マスターからの 2 ~ 3 回のマージ + 競合の修正を含む約 30 件のコミットでプル リクエストを受け取りました。そして、この後、1コミットで明確なPRを獲得しました。
PS ここでは、自動モードでこの手順を実行するためのbashスクリプトを示します。
$ git チェックアウト マスター
$ git ログ --oneline
D
C
B
A
$ git rebase --onto HEAD^^^ HEAD^
$ git ログ --oneline
D
A