我可以用git分割一个已经分割的块吗?


204

我最近patchadd命令中发现了git的选项,我必须说这确实是一个很棒的功能。我还发现,通过敲击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选项不再可用!

Answers:


253

如果您使用的是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 2011年

27
请注意,您确实必须用空格替换它。我尝试过弄清楚自己只能删除-字符,然后Git抱怨我的补丁不适用。
瑞安·伦迪

3
我猜测您删除带有'-'的行并以空格替换'+'的原因是,您正在形成一个补丁,其中那些带有'-'的行已被删除,带有''的行+已添加(在补丁的眼睛)。或以另一种方式看待它,是您实际上执行了这些字符(-,+)所代表的操作(添加一行或删除一行)。仅将其余带有“-”和“ +”的行记录为更改,其余为“文件的状态”。
—atomtomtom

3
@Filype:我不知道为什么会发生这种情况,恐怕-如果您正在运行git add -p并编辑一个大块体e,那只会影响上演的内容,而不影响您的工作树。
马克·朗伊尔

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;
}

那很简单,现在让我们提交。但是,等等,我想在版本控制中保持逻辑上的变更分离,以便进行简单的逐步代码审查,以便我和我的团队可以轻松地搜索提交历史记录中的细节。

从逻辑上讲,删除旧代码与其他样式选择器更改是分开的。我们将需要两个不同的提交,因此让我们添加一个补丁。

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 之间必须保持不变的行,以便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注释删除添加到下一个提交?

我们要将其分为两个提交:

  1. 第一次提交涉及删除一些行(删除评论)。

    要删除已注释的行,只需将其保留,它们已经被标记为跟踪版本控制中的删除,就像我们想要的那样。

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

  2. 第二个提交是更改,通过记录删除和添加来跟踪:

    • 删除(旧的选择器行已删除)

      为了保留旧的选择器行(在此提交期间不要删除它们),我们想要...

      要删除'-'行,请将其设为''

      ...字面上的意思更换负-标志用空格字符。

      所以这三行...

      -
      -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,则可以逐行进行更改。不幸的是,我不知道如何从命令行进行操作-甚至可能。

我过去使用的另一个选项是回滚更改的一部分(保持编辑器处于打开状态),提交我想要的位,撤消并从编辑器中重新保存。不是很优雅,但是可以完成工作。:)


编辑(git-gui用法):

我不确定git-gui在msysgit和linux版本中是否相同,我只使用了msysgit。但是假设它是相同的,则在运行它时,有四个窗格:左上窗格是您的工作目录更改,左下窗格是您的阶段更改,右上是所选文件的差异(是工作目录)或分阶段执行),右下角用于提交说明(我怀疑您不需要它)。单击右上角的文件时,将看到差异。如果右键单击差异线,将看到一个上下文菜单。要注意的两个选项是“提交阶段阶段”和“提交阶段阶段”。您继续选择要提交的行上的“提交阶段行”,就完成了。您甚至可以根据需要选择几行并将其上演。

至于提交,您可以使用gui工具或命令行。


您的第二个命题很明显,但是第一个命题很有趣,您能详细说明一下吗?我已安装,git-gui但不知道如何实现您所描述的内容。
greg0ire 2011年

坦克很多!这可行!我什至能够一键选择我要上演的行并对其进行索引。
greg0ire 2011年

0

一种方法是跳过该块,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年

您是否再次执行了此阶段的大块头?不,Mercurial有插件,Git没有。
阿比森2011年

不,我没有,我希望它们处于同一提交中(但我想如果您的解决方案有效,我可以使用--amend来实现)。我会尝试的。
greg0ire 2011年

如我的回答所说→ git rebase -i。比commit --amend
Abizern
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.