文件 git 提交的更改在合并后消失

Change in a git commit of a file disappears after merge

我在一个特性分支上开发。那时我做了一些其他更改,这些更改已经通过 github 中的 PR 合并到开发分支中,我需要在我的功能分支中进行这些更改。所以我决定将开发分支合并到我的功能分支中。我删除了文件中的一些代码并提交到功能分支中。合并 develop 到 feature 分支后,发现文件的 commit 中删除代码的变化消失了,删除的部分由于合并操作又加回来了。请问:在什么情况下会出现这种情况?谢谢!

更新:

我用github查看历史。这是示例: 这是功能分支 OWL-1697 中此文件的 history of agent.go at the commit 80d82ee in the feature branch OWL-1697. This is the whole history。合并操作后,此文件的 80d82ee 更改消失。

由于您在功能分支中所做的文件更改尚未提交,因此在合并时您可能隐藏了它们。因此,在合并操作时,将这些更改添加回来。

我不建议使用 GitHub 查看提交和文件历史记录。 (GitHub 可能有一些很好的 and/or 奇特的方式来查看这些,但作为 GitHub 的一个非常随意的用户,我不知道有一个。命令行工具有广泛的标志,尽管您必须是 Git 专家才能知道何时使用哪个。)

TL;DR 合并出错原因总结

完成以下文本后,请特别注意 git log 输出的最后几行:

* | | | | | 80d82eef [OWL-1730][common][nqm-mng] Code refactoring
* | | | | | 2438360a [OWL-1667][common][nqm-mng] From `hbs` to `nqm-mng`
| |_|/ / /  
|/| | | |   
* | | | | b598349a Merge pull request #295 from masato25/OWL-1724

在提交 2438360a 中,您添加了一些行,然后在提交 80d82eef 中,您再次将它们删除。

但是,您通过提交 d04492d9:

添加了 相同的
| | * | d04492d9 [OWL-1667][common][nqm-mng] From `hbs` to `nqm-mng`

高一点。您在 2438360a 中添加行的同一天执行此操作。你在 80d82eef 中取出了线,很久以后......但是 在不同的分支 中。在 拓扑顺序 中,您几乎是在将更改放入后立即将其取出……同时还将更改留在单独的分支中。然后,您通过 e1d369d0 将它们带入另一个分支,将它们带入另一个分支,依此类推,直到您将它们带回您认为已将它们带出的分支。

查看提交图

如果我克隆你的存储库并使用 git log --all --decorate --oneline --graph 查看它,我看到这个,部分包括提交 80d82eef(在底部):

* aeecad13 (origin/OWL-1697) [OWL-1730][nqm-mng] Update debug message
* f0797f8e [OWL-1730][nqm-mng] Fix the proble from merge
* 5aaba93b [OWL-1730][nqm-mng] Drop gin's "gopkg.in" paths

[mass snip]

* | | | d2d4debd [OWL-1730][nqm-mng] Tests
* | | | e1037c28 [OWL-1730][nqm-mng] Queue service
* | | |   a847d783 Merge branch 'OWL-1677' into OWL-1697
|\ \ \ \  
| * \ \ \   ea916618 Merge branch 'develop' into OWL-1677
| |\ \ \ \  
| | |/ / /  
| * | | | 056a7442 [OWL-1677] Refactoring testing to usage of Ginkgo
| * | | | 800c3f09 [OWL-1677] Add utilities for testing by Ginkgo framework
| * | | |   85deb914 Merge branch 'develop' into OWL-1677
| |\ \ \ \  
| * | | | | c830da0f [OWL-1677] Fix tests
| * | | | | 14d8571c [OWL-1677] Refactoring test to Ginkgo
| * | | | | 8538306f [OWL-1677] Re-write testing to Ginkgo framework
* | | | | | 906741cd [OWL-1730][nqm-mng] Rename types and methods
* | | | | | 80d82eef [OWL-1730][common][nqm-mng] Code refactoring

我们可以看到提交实际上还在那里,并没有被合并删除。

查找影响文件的提交:--full-history

现在,您在这里关心的文件在提交 80d82eef 中被命名为 modules/nqm-mng/restful/agent.go。正如我们从 --decorate 输出中看到的那样,引导到此处的分支名称是 origin/OWL-1697。但是,修改此特定 文件 的提交有点难找。

要知道的第一个魔法是在将 git log 限制为路径名时使用 --full-history(我怀疑无法让 GitHub 执行此操作)。原因是,如果合并撤消了您想要完成的事情,Git 的 "history simplification" 会删除 对 [=122] 做出贡献的提交=]源的最终版本,使得无法找出哪个合并删除了那个贡献。

第二个要知道的魔法是,在查看合并提交时,我们可能希望 -m 将 Git "split" 合并成两半。

我还使用 --topo-order 强制 Git 以拓扑合理的顺序显示提交(通常没有必要,但在这里通常是个好主意)。

谁做了什么

此时我们可能会准确地查看 80d82eef 对感兴趣的文件做了什么:

$ git show 80d82eef -- modules/nqm-mng/restful/agent.go
commit 80d82eef9606800c094858ac0d60f27ef9ad1307
Author: chyeh <chyeh@cepave.com>
Date:   Fri May 19 11:34:09 2017 +0800

    [OWL-1730][common][nqm-mng] Code refactoring

    Move some code from `common/` to `modules/nqm-mng/` as the preparation
    of the following development.

diff --git a/modules/nqm-mng/restful/agent.go b/modules/nqm-mng/restful/agent.go
index 3ba34901..f21afd05 100644
--- a/modules/nqm-mng/restful/agent.go
+++ b/modules/nqm-mng/restful/agent.go
@@ -124,10 +124,3 @@ func clearCachedTargetsOfAgentById(
        r := commonNqmDb.DeleteCachedTargetsOfAgentById(q.AgentID)
        return mvc.JsonOutputOrNotFound(r)
 }
-
-func nqmAgentHeartbeat(
-       req *commonNqmModel.AgentHeartbeatRequest,
-) mvc.OutputBody {
-       r := commonNqmDb.AgentHeartbeat(req)
-       return mvc.JsonOutputBody(r)
-}

现在我们可以 运行 这个相当长的命令(为了显示目的我把它分成两行):

$ git log --full-history -m -p --topo-order \
    origin/OWL-1697 -- modules/nqm-mng/restful/agent.go

注意三个额外选项(完整历史记录、合并拆分和拓扑顺序)。

输出很长所以我不会全部引用,但显示的提交是:

  • f0797f8e1e2e5a41db30225f4e72dc987b055ac8,其中 re-delete 失败合并带回的行;
  • 7e00e309f0ed5750f6b7b052e77431ec4797d601(相对于第一个 parent d2d4debd),它会重新添加 你不想要的行);
  • 648a324e1333814968a09e4b0277fc0774b4fce6(相对于第一个 parent 447ac685),它只影响 import 行;
  • ccbad82029c50040250a48180caeacfcc57044bd(相对于它的parentda0dcde6),其中re-adds 你不想要的行;
  • dfa34ab98170d62e1bb6d624c2d09f9e4e7e0b57(对比第二个parent 5571dc2c);
  • 219347a6f1649ccfee8e69b481e3166d8d310fe0(相对于它的第二个 parent 1a60e4aa);
  • b11d41be75700c450280a4a5e0edb12381045303(对比第二个parent 28176808);
  • 8f5a0e242fd7c7ded6cdcc4517c33c793b96f8ea(对比第二个parent 5178acdb);
  • e1d369d06a49846f39661642bdfb7c0c81a86b8e(对比第一个 parent 8b1d4f0f);
  • d04492d986fdf1257cb93a5524f2501e767bd564:这是您在 5 月 2 日所做的普通提交,其中添加了您不想要的行;
  • 80d82eef9606800c094858ac0d60f27ef9ad1307:这是您在 5 月 19 日所做的普通提交,其中您删除了不需要的行;
  • 2438360a653e5c158b366f313bf771db4f294147:这是您在 5 月 2 日所做的普通提交,其中添加了您不想要的行;
  • 然后是许多不影响您关心的行的不相关提交,所有这些都早于这些更改。

将这些放在上下文中

根据您进行合并的方式,"most interesting" 往往是 第一个 parent 个。上面就是这种情况。

查看合并的合并基础 也是一个好主意,它带回了您不想要的更改。为此,我们需要 运行 git merge-base 该合并的两个 parent 的两个哈希 ID。提醒一下,合并的哈希 ID 是 7e00e309(或完整的 7e00e309f0ed5750f6b7b052e77431ec4797d601)。所以让我们 运行 git merge-base 在两个 parent 上:

$ git merge-base --all 7e00e309^1 7e00e309^2
b598349a0ba6d6901ef812440746e2dc633c4cdc

提交 "below" 这一点往往不感兴趣。

我们现在可以使用:

git log --decorate --oneline --graph origin/OWL-1697

在完整的上下文中查看所有这些,尽管匹配哈希 ID 非常困难和痛苦。或者,我们可以 运行

git log --decorate --oneline --graph origin/OWL-1697 \
    --full-history -- modules/nqm-mng/restful/agent.go

与他们的任何 parent 提交相比,将此显示剥离为仅提交触摸该文件的提交。结果仍然很长,但现在是 follow-able。让我们跟随它到合并基础,即以 b598349a:

开头的提交
* f0797f8e [OWL-1730][nqm-mng] Fix the proble from merge
*   7e00e309 Merge branch 'develop' into OWL-1697
|\  
| *   648a324e Merge pull request #306 from Cepave/OWL-1771
| |\  
| | * 4d722f8d [OWL-1771] Change `gin`'s import paths
| * |   447ac685 Merge branch 'roby-testing' into develop
| |\ \  
| * | | ee1daba9 Merge pull request #305 from masato25/OWL-1674_ma
| | |/  
| |/|   
| * |   ccbad820 Merge pull request #303 from masato25/OWL-1740
| |\ \  
| * \ \   69a9ee6e Merge pull request #302 from masato25/OWL-1765
| |\ \ \  
| | * \ \   9e9d1a55 Merge branch 'develop' into OWL-1765
| | |\ \ \  
| | |/ / /  
| |/| / /   
| | |/ /    
| * | |   dfa34ab9 Merge pull request #300 from masato25/OWL-1740
| |\ \ \  
| | |/ /  
| * | |   219347a6 Merge pull request #301 from masato25/OWL-1755
| |\ \ \  
| | |/ /  
| * | |   b11d41be Merge pull request #299 from masato25/OWL-1755
| |\ \ \  
| | |/ /  
| | | /   
| | |/    
| |/|     
| * |   8f5a0e24 Merge pull request #298 from humorless/OWL-1644-c
| |\ \  
| * \ \   e1d369d0 Merge pull request #286 from Cepave/OWL-1667
| |\ \ \  
| | |/ /  
| |/| |   
| | * | d04492d9 [OWL-1667][common][nqm-mng] From `hbs` to `nqm-mng`
| * | |   8b1d4f0f Merge pull request #297 from hitripod/develop
| |\ \ \  
| * | | | 05e45dc8 Merge pull request #296 from masato25/OWL-1765
| | |_|/  
| |/| |   
* | | |   a847d783 Merge branch 'OWL-1677' into OWL-1697
|\ \ \ \  
| * \ \ \   ea916618 Merge branch 'develop' into OWL-1677
| |\ \ \ \  
| | |/ / /  
| |\ \ \ \  
| | |/ / /  
| * | | |   85deb914 Merge branch 'develop' into OWL-1677
| |\ \ \ \  
* | | | | | 80d82eef [OWL-1730][common][nqm-mng] Code refactoring
* | | | | | 2438360a [OWL-1667][common][nqm-mng] From `hbs` to `nqm-mng`
| |_|/ / /  
|/| | | |   
* | | | | b598349a Merge pull request #295 from masato25/OWL-1724
| |_|/ /  
[snip]

此输出包含合并出错的所有原因。就 Git 而言,在提交 2438360a80d82eef 中添加然后立即删除这些行是完全无关紧要的。重要的是在 d04492d9 中独立和 never-undone 添加那些 相同的 行。这是一系列合并带来的变化的来源,最终由合并 7e00e309 带来。所有 Git 可以说的是那些行 应该 在那里,因为它们是由一个 "side" 合并添加的,而另一边什么也没做文件!