【问题标题】:Handling temporary changes (not to be committed) in Git在 Git 中处理临时更改(不提交)
【发布时间】:2011-11-01 03:28:52
【问题描述】:

经常在分支上工作时,我需要引入一些“临时”更改(例如额外的调试信息,或者让我更好地观察我正在实际工作的事情的更改)。

关于这些“临时”更改:

  • 我希望它们在我的分支的工作副本中,因为它们可以帮助我进行实际的更改,
  • 我不希望它们提交到分支,因为该分支将在一段时间内合并到 master 中,并且它们不是生产代码。

目前我只是将它们保持为非暂存状态,并在暂存每个提交时手动跳过它们。但是我不能继续使用这个解决方案,因为:

  • 我必须始终记住需要跳过哪些文件,
  • 有一天我会在一个文件中进行 2 处更改,一个是临时的,一个是要提交的,这真的很麻烦。

我应该如何处理?


gitignore 显然是不可能的,因为我不想忽略整个文件,而且我仍然对其他提交者的更改感兴趣(我需要不时将分支变基为 master)。

【问题讨论】:

  • 尝试将忽略扩展到大块粒度似乎是一个有趣的想法。甚至可能值得尝试在 git 邮件列表上询问(您不必订阅帖子,因为它的数量相当大,您可能不想这样做)。
  • 其实 gitignore 是没有问题的,因为如果文件是版本控制的,你得到它的提交版本。只有添加会忽略它。但是,当您只想忽略对特定文件的某些更改并且迟早您确实想要忽略时,它不会处理这种情况。
  • 我添加了自己的想法,对我来说看起来不错,但如果没有问题,如果有经验的人可以看看,我将不胜感激。
  • 正要问同样的问题。 .hunkignore 会很酷。然而,rebase 解决方案似乎很有效。

标签: git branch git-branch


【解决方案1】:

我通常使用以下方法处理这个问题:

git add -p

... 逐个进行更改。然后,您只需确保按 n 进行调试更改。


如果我有更多涉及这种类型的更改,我将创建一个名为 local-changes 的分支,并在其提示处提交一个引入调试代码的提交。在创建更多提交后,我会使用:

git rebase -i master

... 对它们进行重新排序,以便再次提交带有本地更改的提交。然后更新master并返回本地更改分支,您可以这样做:

git checkout master
git merge local-changes^
git checkout local-changes

【讨论】:

  • 手动选择相关更改是我在这里试图避免的:) 我只想做一次。
  • :) 好吧,我在回答中添加了一个替代建议。
【解决方案2】:

试试git update-index --assume-unchanged <file>。这样git在使用git addgit commit -a时不会将文件添加到索引中。

编辑:这不允许您处理一个文件同时具有临时和永久更改的情况。

【讨论】:

  • 可能值得指出使用--assume-unchanged 的后果也可能令人困惑:)
  • @Mark 我在使用--assume-unchanged 时从未感到困惑。你能详细说明吗?我遇到过一两次的唯一困难是找出哪些文件设置了这个标志。
  • 这很棒。来自文档:“如果 Git 需要修改索引中的这个文件,例如在提交中合并时,Git 将失败(优雅地);”。如果它在发生这种情况时取消设置假设不变的位会很好,但我认为不会。另外,如果git status 提醒您assume-unchanged 文件,那就太好了。
  • 我使用别名ignored = !git ls-files -v | grep "^[[:lower:]]" 来检查以这种方式标记的文件。
【解决方案3】:

这里有一种处理方法,一旦设置好,您只需要记住设置它的一个步骤,以及每次推送之前的一个步骤。

设置:

git branch tempChanges  [branch for temporary changes]
  [create your temporary changes]
git add -A
git commit

注意该提交的 sha。然后切换到你的工作分支,然后:

git cherry-pick shaOfTempChangesCommit

现在您的工作分支上已经有了更改。做你的工作并做出承诺。然后,在你推送之前:

git rebase -i

你会看到这样的东西:

pick bfd4d2e This first commit is your temporary changes.
pick 186a99d Some stuff done on the working branch.
pick ec871c6 More stuff done on the working branch.
(etc.)

删除包含临时更改的行。 然后保存并退出。您的历史记录将被重写以排除临时更改。 (更改仍将存在于 tempChanges 分支中。)完成后,进行所需的任何测试,然后 git push.

当您准备好再次工作时,您可以将临时更改拉回您当前的工作分支(或新的工作分支):

git cherry-pick shaOfTempChangesCommit

所以,总之,在这个方法中你只需要记住

  • 创建工作分支后

    git cherry-pick shaOfTempChangesCommit

  • 在你完成工作并准备推送之后

    git rebase -i[在推送之前删除临时更改]

【讨论】:

    【解决方案4】:

    你可以使用

    git stash
    

    将其保存到临时空间中。完成合并后,您可以使用

    git stash pop
    

    将您的临时更改加载回您的工作目录。

    【讨论】:

    • 这不会按照 OP 的要求区分有用的全局更改和仅本地更改..
    【解决方案5】:

    我通常将我所有的调试代码放在它自己的提交中,然后在我进行合并之前,我revert那个提交。我有时会使用大多数其他答案的一些变体,但我喜欢这个答案是因为它的简单性和它保留了我的开发历史的事实。是的,我不希望我的调试代码出现在最终产品中,因此是 revert,但如果测试发现问题,我希望能够恢复该调试代码以进行进一步的工作。

    【讨论】:

      【解决方案6】:

      我找到了一个干净的解决方案来解决这个问题:(请原谅我的 ascii-art)。它需要主题分支的附加分支。 (这有缺陷,正在争议/纠正,见 cmets)

      作品最初是这样的:

      master
           \
            \
           commit1  ---- commit2 ---- "branch"
      

      工作在“分支”上完成。

      引入一些临时更改:

      • 从“master”创建分支“branch-temp”
      • 在那里提交临时更改
      • 将“branch”从“master”重新定位到“branch-temp”

      回购现在看起来像:

      master
           \
            \
           "branch-temp" ----- commit1 ---- commit2 ---- "branch"
      

      分支上的工作现在愉快地继续,临时更改在状态中不可见。

      更改或扩展临时更改:

      • 结帐分支临时
      • commit --amend 那里的临时更改 - 这是错误的,因为它使“branch-temp”发散

      合并从分支到主分支的更改

      这有点棘手。我们希望合并所有更改,除了“branch-temp”引入的更改。我的想法是:

      • 运行从“分支”到“主”的正常合并
        (我们现在有一个合并,但有一些不必要的临时更改 - 让我们删除它们)
      • git revert --no-commit branch-temp
      • git commit --amend
        (这两个步骤应该修改合并提交,使其不再包含来自分支临时的更改)

      【讨论】:

      • 我会改为使用交互式 rebase 重新设置到 master 上,并删除不使用的提交(标有 [test] 或主题中的其他内容)。这也将避免对“branch-temp”的需要并导致线性历史记录。
      • git checkout branch-temp + git commit --amend 将无法正常工作,因为之后branch-temp 将拥有新版本,但branch 仍将拥有旧版本的提交。而且我不确定普通的git rebase --onto branch-temp 会解决这个问题。 git rebase -i 并以这种方式编辑提交更容易,但这会将 branch-temp 抛在后面(这就是我将使用的,并使用 rebase 或合并 + 还原来删除提交)。
      • 是的,你是对的——我检查了文档并提交 --amend 创建了一个新的提交并更新了当前分支,而我认为它修改了 HEAD 上的提交。
      • @Jan,如果不是修改,我只是简单地向branch-temp 添加一个新的提交,然后将branch 重新设置为branch-temp 的新负责人,这是否正确?合并的方式也需要修改......我最满意的是不需要我实际修改主题分支的方式,以防我需要恢复它的工作。
      • 是的,它是正确的。广告恢复虽然没用。当您将分支合并到 master 并还原临时提交时,而不是稍后从 master 合并到分支时,您还将合并反转,因此无论如何您都不会有临时更改。
      【解决方案7】:

      如何编写一个简单的 shell 脚本,根据请求修补和撤消您的调试更改(然后将其设为 git 别名)。

      例如

      git apply-my-debug
      ...
      do coding
      ...
      git remove-my-debug
      git add .
      git commit -m "Don't worry about debug changes"
      

      【讨论】:

        【解决方案8】:

        为避免在创建功能时弄乱暂存区域,提交调试更改并发出明亮闪烁的警告,提示它们不应进入最终合并:

        #warning - DEBUG ONLY - DO NOT MERGE
        
        print(debugInfo)
        
        #warning - DEBUG ONLY - DO NOT MERGE
        

        当您准备好合并分支时,如果您忘记了它们,这些更改将被您或其他人在您的拉取请求的代码审查中捕获。

        然后,您将有不同的方法来删除调试提交:

        1. revert 特定的调试提交。这将在分支中保留他们的历史记录。

        2. cherry-pick good 提交。这将完全删除调试提交。

        3. 更复杂的东西,例如 rebase -interactive 以删除就地提交。

        【讨论】:

          【解决方案9】:

          GIT 的 stash 功能可以满足您的需求。至少对于“保持”部分。不能像这样避免在提交时做出好/坏选择。

          【讨论】:

            【解决方案10】:

            我倾向于保留这样未提交的更改。我总是使用git add -igit add -p 来进行更改(除非我确定我想要树的所有更改)。这样我就可以查看我想要提交的所有更改并轻松跳过临时更改。它还有助于暂存您知道要尽早提交的更改,并保持它们暂存甚至提交,而不是使用git commit --amend 添加更多更改。

            【讨论】:

              猜你喜欢
              • 2021-11-05
              • 1970-01-01
              • 2015-03-10
              • 2021-02-15
              • 1970-01-01
              • 2018-11-27
              • 2014-07-12
              • 2015-01-16
              • 2015-12-04
              相关资源
              最近更新 更多