すでに分割されているハンクをgitで分割できますか?


205

私は最近コマンドにgitのpatchオプションを発見しましたaddが、それは本当に素晴らしい機能だと言わざるを得ません。また、sキーを押すと、大きなハンクが小さなハンクに分割され、コミットの精度が高まることも発見しました。しかし、スプリットハンクが十分に小さくない場合、さらに精度を上げるにはどうすればよいでしょうか。

たとえば、次のすでに分割されたハンクについて考えてみます。

@@ -34,12 +34,7 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */
-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {
+#user-register form.table-form .field-type-checkbox label {
   width: 300px;
 }

CSSコメントの削除を次のコミットにのみ追加するにはどうすればよいですか?このsオプションはもう利用できません!

回答:


254

を使用git add -pしていて、で分割した後でも、s十分な小さな変更がない場合は、を使用eしてパッチを直接編集できます。

これは少し混乱するかもしれませんが、押した後に開かれるエディタウィンドウの指示に注意深く従えば、e問題はありません。引用した場合-は、これらの行の先頭にあるスペースに置き換えます。

-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {

...そして、次の行、つまりで始まる行を削除し+ます。その後、エディターを保存して終了すると、CSSコメントの削除のみがステージングされます。


9
クールなソリューション!私はそれを見ましたが、誤解されていました...変更は作業ツリーからも削除されるでしょう。
greg0ire 2011年

7
確かに、それはヘルプテキストからはあまり明白ではありません。私は実際にこれをたくさん使っています。なぜなら、gitは各コミットをできるだけ正確で美しいものにすることを本当に勧めているからです:)
Mark Longair

27
実際にはスペースで置き換える必要があることに注意してください。-文字を削除するだけでよいと考えてみましたが、Gitは私のパッチが適用されないことを訴えました。
Ryan Lundy

3
「-」の行を削除して「+」をスペースに置き換える理由は、「-」の行がすでに削除されており、「-」の行がすでに削除されているパッチを形成しているためだと思います+はすでに追加されています(パッチの目で)。または、別の見方をすると、それらの文字(-、+)が表すアクション(行の追加または削除)を実際に実行します。'-'と '+'を含む残りの行のみが変更として記録され、残りは「ファイルの状態」です。
atomictom '19

3
@Filype:なぜそれが起こったのかはわかりません、私は恐れています-もしあなたがgit add -pハンクを実行して編集していた場合、それはeステージングされたものだけに影響し、作業ツリーには影響しません。
マークロングエアー、2015

60

example.css次のようになっているとします。

.classname {
  width: 440px;
}

/*#field_teacher_id {
  display: block;
} */

form.table-form #field_teacher + label,
form.table-form #field_producer_distributor + label {
  width: 300px;
}

.another {
  width: 420px;
}

次に、真ん中のブロックのスタイルセレクターを変更します。その間に、不要になった古いコメントアウトスタイルをいくつか削除します。

.classname {
  width: 440px;
}

#user-register form.table-form .field-type-checkbox label {
  width: 300px;
}

.another {
  width: 420px;
}

それは簡単でした、今コミットしましょう。しかし、待ってください。単純な段階的なコードレビューのためにバージョン管理の変更の論理的な分離を維持し、チームと私がコミット履歴で簡単に詳細を検索できるようにしたいと考えています。

古いコードの削除は、他のスタイルセレクターの変更とは論理的に分離されています。2つの異なるコミットが必要になるので、パッチのハンクを追加しましょう。

git add --patch
diff --git a/example.css b/example.css
index 426449d..50ecff9 100644
--- a/example.css
+++ b/example.css
@@ -2,12 +2,7 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */
-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {
+#user-register form.table-form .field-type-checkbox label {
   width: 300px;
 }

Stage this hunk [y,n,q,a,d,/,e,?]?

おっと、変更が近すぎるように見えるので、gitはそれらをまとめました。

を押して分割しようとしてもs、分割は精度の変更に十分な粒度ではないため、同じ結果になります。gitがパッチを自動的に分割できるようにするには、変更された行の間に変更されていない行が必要です

だから、手動で編集してみましょうe

Stage this hunk [y,n,q,a,d,/,e,?]? e

gitは、選択したエディターでパッチを開きます。

# Manual hunk edit mode -- see bottom for a quick guide
@@ -2,12 +2,7 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */
-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {
+#user-register form.table-form .field-type-checkbox label {
   width: 300px;
 }

# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
#
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging. If it does not apply cleanly, you will be given
# an opportunity to edit again. If all lines of the hunk are removed,
# then the edit is aborted and the hunk is left unchanged.

目標を確認してみましょう。

CSSコメントの削除を次のコミットにのみ追加するにはどうすればよいですか?

これを2つのコミットに分割します。

  1. 最初のコミットには、いくつかの行の削除が含まれます(コメントの削除)。

    コメント付きの行を削除するには、そのままにしておきます。必要に応じて、バージョン管理での削除を追跡するようにマークされています。

    -/*#field_teacher_id {
    - display: block;
    -} */

  2. 2番目のコミットは変更であり、削除と追加の両方を記録することによって追跡されます。

    • 削除(古いセレクタ行は削除されました)

      古いセレクター行を保持するには(このコミット中にそれらを削除しないでください)、私たちは...

      '-'行を削除するには、それらを ''にします

      ...これは、文字どおりマイナス-記号をスペース文字に置き換えることを意味します。

      したがって、これらの3行...

      -
      -form.table-form #field_teacher + label,
      -form.table-form #field_producer_distributor + label {

      ...次のようになります(3行すべての最初の単一のスペースに注意してください):


      form.table-form #field_teacher + label,
      form.table-form #field_producer_distributor + label {

    • 追加(新しいセレクタ行が追加されました)

      このコミット中に追加された新しいセレクター行に注意を払わないために、私たちは...

      「+」行を削除するには、それらを削除します。

      ...これは文字通り行全体を削除することを意味します:

      +#user-register form.table-form .field-type-checkbox label {

      (ボーナス:エディターとしてvimを使用している場合は、を押しddて行を削除してください。NanoユーザーはCtrl+を押しますK

保存すると、エディターは次のようになります。

# Manual hunk edit mode -- see bottom for a quick guide
@@ -2,12 +2,7 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */

 form.table-form #field_teacher + label,
 form.table-form #field_producer_distributor + label {
   width: 300px;
 }

# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
#
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging. If it does not apply cleanly, you will be given
# an opportunity to edit again. If all lines of the hunk are removed,
# then the edit is aborted and the hunk is left unchanged.

コミットしましょう。

git commit -m "remove old code"

念のため、最後のコミットからの変更を見てみましょう。

git show
commit 572ecbc7beecca495c8965ce54fbccabdd085112
Author: Jeff Puckett <jeff@jeffpuckett.com>
Date:   Sat Jun 11 17:06:48 2016 -0500

    remove old code

diff --git a/example.css b/example.css
index 426449d..d04c832 100644
--- a/example.css
+++ b/example.css
@@ -2,9 +2,6 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */

 form.table-form #field_teacher + label,
 form.table-form #field_producer_distributor + label {

完璧-削除のみがそのアトミックコミットに含まれていたことがわかります。それでは、ジョブを完了して残りをコミットしましょう。

git add .
git commit -m "change selectors"
git show
commit 83ec3c16b73bca799e4ed525148cf303e0bd39f9
Author: Jeff Puckett <jeff@jeffpuckett.com>
Date:   Sat Jun 11 17:09:12 2016 -0500

    change selectors

diff --git a/example.css b/example.css
index d04c832..50ecff9 100644
--- a/example.css
+++ b/example.css
@@ -2,9 +2,7 @@
   width: 440px;
 }

-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {
+#user-register form.table-form .field-type-checkbox label {
   width: 300px;
 }

最後に、最後のコミットにはセレクターの変更のみが含まれていることがわかります。


1
ボーナス#2:あなたは、あなたのエディタとしてVIMを使用することが起こる場合は、行を削除するには、キーボード上の二回「D」キーを押しする必要があります:D
Alexxus

3
また、代わりにあなたが追加したくない追加された行を除去するには、置き換えることができ+#。結果は同じですが、削除することに不快である(そして元に戻すことができない)か、保存する前に実験したい場合があります。
ob-ivan

そしてそれは、vimのためにあるr #の上にプラスのxD
aksh1618

目標は「CSSコメントの削除を次のコミットにのみ追加するにはどうすればよいですか?」ですが、それが何を達成しているのかについてのステップは本当に混乱しています。(次のコミットへの数行の「削除」のみを「追加」したいので)単に削除または追加と言うのは非常に混乱します。各ステップで何が達成されたかを説明すると、明確になります。
ahnbizcad

9

git guiを使用できる場合は、変更を行ごとにステージングできます。残念ながら、コマンドラインから、またはそれが可能であるとしても、それを行う方法がわかりません。

過去に使用したもう1つのオプションは、変更の一部をロールバック(エディターを開いたままにする)、必要なビットをコミット、元に戻す、エディターからの再保存です。あまりエレガントではありませんが、仕事は完了です。:)


編集(git-guiの使用):

git-guiがmsysgitとlinuxのバージョンで同じかどうかはわかりませんが、msysgitのみを使用しました。しかし、同じであると仮定すると、実行すると、4つのペインがあります。左上のペインは作業ディレクトリの変更、左下はステージの変更、右上は選択したファイルの差分です(作業ディレクトリであっても)または段階的)、および右下はコミットの説明です(私はあなたがそれを必要としないと思います)。右上のファイルをクリックすると、差分が表示されます。diff行を右クリックすると、コンテキストメニューが表示されます。注意すべき2つのオプションは、「ステージハンクコミット」と「ステージラインコミット」です。コミットしたい行で「ステージ行のコミット」を選択し続けると、完了です。複数のラインを選択して、必要に応じてステージングすることもできます。

コミットに関しては、guiツールまたはコマンドラインを使用できます。


2番目の命題は明白ですが、最初の命題は興味深いものです。もう少し詳しく説明していただけますか。インストールしましたgit-guiが、あなたが説明していることを達成する方法がわかりません。
greg0ire 2011年

タンクがたくさん!これでうまくいきます!ステージングしたい行を選択して、ワンクリックでインデックスを作成することもできました。
greg0ire 2011年

0

それを行う1つの方法は、チャンクをスキップし、git add他に必要なことをすべて実行git addしてから、再度実行することです。これが唯一のチャンクである場合は、分割することができます。

コミットの順序が心配な場合は、を使用してくださいgit rebase -i


これは私が試したものであり、私の質問の塊は、git add -pもう一度実行したときに唯一のものですが、分割することはできません。私はこれを得ます:Stage this hunk [y,n,q,a,d,/,e,?]?そして 's'を押すとヘルプが出力されます。ところで、そうではadd patchありませんpatch addか?または、git patchインストールする必要があるプラグインはありますか?
greg0ire 2011年

これをもう一度実行する前に、ステージングされたhunkをコミットしましたか?Mercurialにはプラグインがありますが、Gitにはありません。
Abizern、2011年

いいえ、しませんでした。同じコミットにしたいのですが(あなたの解決策がうまくいけば、-amendを使用してこれを実現できます)。やってみます。
greg0ire 2011年

私の答えが言ったように→ git rebase -i。どちらがより柔軟ですかcommit --amend
Abizern
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.