【问题标题】:Can I split an already split hunk with git?我可以用 git 拆分已经拆分的块吗?
【发布时间】:2011-09-10 17:30:43
【问题描述】:

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

【问题讨论】:

    标签: git split add patch


    【解决方案1】:

    假设您的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 才能自动拆分补丁。

    所以,让我们手动编辑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 {

        ...将变为(notice所有 3 行中第一行的单个空格):

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

    最后你可以看到最后一次提交只包括选择器的变化。

    【讨论】:

    • Bonus #2: 如果你碰巧使用 VIM 作为你的编辑器,你必须在键盘上按两次“d”来删除一行:D
    • 另外,您可以将+ 替换为#,而不是删除您不想添加的行。结果是一样的,但也许您对删除(并且无法恢复)感到不舒服,或者您想在保存之前进行试验。
    • 而且,对于 vim 来说,r # 超过了 xD
    • 目标是“我如何才能将 CSS 注释删除仅添加到下一次提交?”,但这些步骤对于它所完成的工作确实令人困惑。 (我们只想在下一次提交中“添加”几行的“删除”。)所以简单地说删除或添加是非常令人困惑的。说明每个步骤完成了什么有助于澄清。
    【解决方案2】:

    如果你使用git add -p,即使在使用s分割后,你也没有足够小的变化,你可以使用e来编辑补丁直接。

    这可能有点令人困惑,但如果您仔细按照按 e 后将打开的编辑器窗口中的说明进行操作那么你会没事的。在您引用的情况下,您可能希望在这些行的开头用空格替换 -

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

    ... 并删除以下行,即以+ 开头的行。如果您随后保存并退出您的编辑器,则只会移除 CSS 注释。

    【讨论】:

    • 很酷的解决方案!我看到了,但误解了......我虽然这些更改也会从工作树中删除。
    • 确实,从帮助文本中看不是很明显。实际上,我发现自己经常使用它,因为我认为 git 确实鼓励您使每个提交尽可能精确和美观:)
    • 请注意,您确实必须将其替换为 空格。我尝试了一下,认为我可以删除 - 字符,但 Git 抱怨我的补丁不适用。
    • 我猜你删除带有'-'的行并用空格替换'+'的原因是你正在形成一个补丁,其中那些带有'-'的行已经已删除,并且已经添加了带有“+”的行(在补丁的眼睛中)。或者另一种看待它的方式,您实际上是在执行这些字符 (-,+) 所代表的操作(添加或删除一行)。只有带有 '-'s 和 '+'s 的其余行被记录为更改,其余的就是“文件的原样”。
    • @Filype:我不知道为什么会发生这种情况,恐怕 - 如果你正在运行 git add -p 并用 e 编辑了一个大块,那只会影响上演的内容,而不是你的工作树。
    【解决方案3】:

    一种方法是跳过块,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 插件?
    • 你在再次运行之前提交了分阶段的帅哥吗?不,Mercurial 有插件,Git 没有。
    • 不,我没有,我希望它们在同一个提交中(但我想如果你的解决方案有效,我可以使用 --amend 来实现这一点)。我试试看。
    • 正如我的回答所说 → git rebase -i。哪个比commit --amend更灵活
    【解决方案4】:

    如果您可以使用 git gui,它允许您逐行进行更改。不幸的是,我不知道如何从命令行执行此操作 - 或者即使有可能。

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


    编辑(git-gui 用法):

    我不确定 git-gui 在 msysgit 和 linux 版本中是否相同,我只使用了 msysgit 之一。但是假设它是相同的,当你运行它时,有四个窗格:左上窗格是您的工作目录更改,左下是您的阶段更改,右上角是所选文件的差异(无论是工作目录或暂存),右下角用于描述提交(我怀疑你不需要它)。当您单击右上角的文件时,您将看到差异。如果您右键单击差异线,您将看到一个上下文菜单。需要注意的两个选项是“stage hunk for commit”和“stage line for commit”。您继续在要提交的行上选择“stage line for commit”,然后就完成了。如果需要,您甚至可以选择多条线并将它们分阶段。您可以随时单击暂存框中的文件以查看您要提交的内容。

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

    【讨论】:

    • 你的第二个命题很明显,但第一个很有趣,你能再详细一点吗?我安装了git-gui,但我不知道如何实现你所描述的。
    • 坦克很多!这行得通!我什至可以一键选择我想要暂存的行并为其编制索引。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-16
    • 2020-07-07
    • 1970-01-01
    相关资源
    最近更新 更多