238

私はgit内のリベース機能全体に少し慣れていません。次のコミットを行ったとしましょう。

A -> B -> C -> D

その後、にD追加されたいくつかの新しいコードに依存する修正が含まれているAこと、およびこれらのコミットが一緒に属していることに気付きました。どうすれば押しつぶしAD一緒に、離れて一人でいることができBますCか?

4

5 に答える 5

344

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

于 2010-10-13T07:55:49.283 に答える
47

注:結果が分からない限り、別のリポジトリにプッシュされたコミットを変更しないでください。

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。コミットADて、履歴にはもうありませんが、消えていません。この時点でまだそれらを復元できますが、しばらくの間はgit rebase --hard D(によってgit rebase --hardローカルの変更が破棄されます! )。

于 2013-06-21T15:43:15.957 に答える
3

SourceTreeを使用している場合:

まだコミットをプッシュしていないことを確認してください。

  1. リポジトリ > インタラクティブ リベース...
  2. D (新しいコミット) を A (古いコミット) の真上にドラッグします。
  3. コミット D が強調表示されていることを確認します
  4. クリックSquash with previous
于 2016-04-15T13:34:39.697 に答える
1

インタラクティブなリベースは、20 ~ 30 個のコミットを含む大きな機能ブランチが作成されるまで、および/またはマスターからのマージがいくつか行われるまで、またはブランチでコミットしている間に競合が修正されるまではうまく機能します。履歴からコミットを見つけて置き換えても、ここでは機能picksquashません。だから私は別の方法を探していて、この記事を見つけました。別のブランチでこれを機能させるために変更を加えました。

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スクリプトを示します。

于 2018-10-10T06:47:33.213 に答える
-1

$ git チェックアウト マスター

$ git ログ --oneline

D
C
B
A

$ git rebase --onto HEAD^^^ HEAD^

$ git ログ --oneline

D
A
于 2010-10-13T11:17:57.657 に答える