たとえば、ファイルの削除はキャプチャされません。
$ git checkout draft_feature_a $(git diff --name-only master draft_feature_a)
error: pathspec 'ttt.py' did not match any file(s) known to git.
実際の rebase-and-squash-etc で同じことを行うことができます (以下で "fixup" を使用しましたが、ほとんど同じことです。元のコミットはすべて で引き続き表示できますdraft_feature_a
)。
$ git checkout -b draft_feature_a
[work, commit, etc - I made two commits: add newfile and rm ttt.py]
$ git checkout master
Switched to branch 'master'
$ git checkout -b feature_a
Switched to a new branch 'feature_a'
$ git merge draft_feature_a
Updating 523bacb..3a486fc
Fast-forward
newfile | 0
ttt.py | 14 --------------
2 files changed, 14 deletions(-)
create mode 100644 newfile
delete mode 100644 ttt.py
git rebase -i master
[edit to make everything but the first a "fixup"]
...
2 files changed, 14 deletions(-)
create mode 100644 newfile
delete mode 100644 ttt.py
Successfully rebased and updated refs/heads/feature_a.
$ git commit --amend
[edit commit message]
私は実際にこのようなワークフローをよく使用しますが、ほとんどの場合、ドラフト作業を「git rebase -i」するだけです。別の「ドラフト」ブランチを作成するかどうかに関係なく、元のコミットが利用可能であることに注意してください。それらは名前を失うだけであり、コミット ID を見つけるために reflog を掘り下げる必要があります。新しいブランチを作成して「git merge」する代わりに、新しい名前を追加できます。
(まず、前の例をクリーンアップしましょう)
$ git checkout master
Switched to branch 'master'
$ git branch -D draft_feature_a
Deleted branch draft_feature_a (was 3a486fc).
$ git branch -D feature_a
Deleted branch feature_a (was 0fc36f0).
(今は新しい例です)
$ git checkout -b feature_a
Switched to a new branch 'feature_a'
[work work work]
[time to clean up, let's stick a label on this version so I can find it easily:]
$ git branch messy_feature_a feature_a
$ git rebase -i master
リベースが完了し、すべてが押しつぶされ、修正され、再配置され、コミットメッセージが編集されたなど、何かを台無しにしたと判断した場合でも、すべての「ドラフト」(低品質/乱雑)の作業は引き続き利用できます「乱雑な」名前で名前で。満足して古い名前が不要になったら、手動で削除します ( git branch -D
)。
これを理解するための秘訣は、git で何かを行うたびに、新しいコミットのみを追加するということです。古いものは、(最終的に) それらを「ガベージ コレクション」するために暗黙的または明示的な何かを行うまで、リポジトリに残ります。3a486fc
スタイル SHA1 名以外でコミットを名前付けできるようにするブランチ ラベル名 (またはタグなどの他の「目に見える」名前) がある限り、それらは「永久に」存続します。ブランチを削除すると、単にラベルが消去されます。1 ~ 3 か月後、ラベルのないコミットは最終的にガベージ コレクションされます。(より正確には、有効期限が切れるまで reflog に名前が残っています。reflog エントリには時間制限があります。 のドキュメントgit reflog
、特に--expire=<time>
パラメータを参照してください。)
同様に、「リベース」は新しい一連のコミットを作成し、そこにすべての古いコミットを残します。リベースが完了すると、git は古い一連のコミットの末尾からラベルを剥がし、それを新しい一連のコミットの末尾に貼り付けます。
A -- B -- C [label: master]
\
D -- E [label: feature_a]
[rebase feature_a on master, and squash or fixup to make commit DE which is D+E]
A -- B -- C [label: master]
| \
| D -- E [no label!]
\
DE [label: feature_a]
リベースを行う前に余分なラベルを追加すると、現在のブランチのfeature_a
ラベルは剥がされて新しいコミットに移動されますが、他のラベル ( messy_feature_a
) は残り、コミット E に簡単にアクセスできます。チェーン (C から分岐する D と E)。