查找git提交的直接祖先(父提交?)

4

开始一个新的代码库并添加一些提交记录:

#( 03/01/17@10:50am )( tim@tim ):~
   mkdir test && cd test && git init

Initialised empty Git repository in /home/tim/test/.git/

.

#( 03/01/17@11:17am )( tim@tim ):~/test@master✔
   touch readme && git add --all && git commit -am "readme"   

[master (root-commit) 1b7f299] readme
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 readme

.

#( 03/01/17@11:17am )( tim@tim ):~/test@master✔
   touch howto && git add --all && git commit -am "howto" 

[master fd46c4c] howto
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 howto

.

#( 03/01/17@11:19am )( tim@tim ):~/test@master✔
   touch la && git add --all && git commit -am "add la"

[master 4680089] add la
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 la

.

#( 03/01/17@11:20am )( tim@tim ):~/test@master✔
   ls
howto  la  readme

#( 03/01/17@11:20am )( tim@tim ):~/test@master✔
   echo "hello" >> readme && echo "hello" >> howto

#( 03/01/17@11:20am )( tim@tim ):~/test@master✗✗✗
   git commit -am "edit readme and howto"
[master 8969440] edit readme and howto
 2 files changed, 2 insertions(+)

现在我们有以下提交记录:

commit 8969440d52e578113f609d948e6ffd06cec96fa9
Author: Tim Richardson <tim@x.com>
Date:   Wed Mar 1 11:20:54 2017 +0000

    edit readme and howto

commit 4680089c7c1a0ead84f6b2973fd6d9e1356fd5c0
Author: Tim Richardson <tim@x.com>
Date:   Wed Mar 1 11:20:06 2017 +0000

    add la

commit fd46c4cf593752ec8163d8db21042c8dd336f529
Author: Tim Richardson <tim@x.com>
Date:   Wed Mar 1 11:18:09 2017 +0000

    howto

commit 1b7f299c5ad4fc50ce4913ab4cdbbdc761db0487
Author: Tim Richardson <tim@x.com>
Date:   Wed Mar 1 11:17:50 2017 +0000

    readme

让我们创建一个名为test的新分支,并将其重置为初始提交:

#( 03/01/17@11:26am )( tim@tim ):~/test@master✔
   git checkout -b test
Switched to a new branch 'test'

#( 03/01/17@11:27am )( tim@tim ):~/test@test✔
   git reset --hard 1b7f299c5ad4fc50ce4913ab4cdbbdc761db0487

HEAD is now at 1b7f299 readme

如果我选择挑选提交记录8969440,它会失败,因为它依赖于fd46c4c和1b7f29,但不依赖于4680089:

#( 03/01/17@11:27am )( tim@tim ):~/test@test✔
   git cherry-pick 8969440
error: could not apply 8969440... edit readme and howto
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

然而,即使4680089c7不是git日志上的一级后代,我也可以毫无冲突地从1b7f299c中挑选出它:

#( 03/01/17@11:28am )( tim@tim ):~/test@test✗✗✗
   git reset --hard 

HEAD is now at 1b7f299 readme

#( 03/01/17@12:10pm )( tim@tim ):~/test@test✔
   git cherry-pick 4680089c7

[test de3878f] add la
 Date: Wed Mar 1 11:20:06 2017 +0000
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 la

因此,补丁之间存在依赖关系图,如下所示:

+---------+
|         |
| 1b7f299 +--------+
|         |        |
+---------+        |      +----------+
                   +----->+          |
                   |      | 8969440  |
+---------+        |      |          |
|         |        |      +----------+
| fd46c4c +--------+
|         |
+---------+


+---------+
|         |
| 4680089 |
|         |
+---------+

我的问题是:在一个大型代码库中,如何计算依赖关系图,并以补丁的形式呈现?我该如何使用 Git 来确定哪些提交依赖于其他提交?

2个回答

1
标题中的问题的答案是,找到提交的父级(们):
git log --pretty=%p <commit>

%P代表完整的sha1。

但这并不是你所期望的。

假设在你的情况下有提交A和B,而B依赖于A。可能A是B的父提交。B也可能比A多出许多提交。

尝试将B挑选到当前分支(例如master),然后发生冲突。运行git status以查看哪些文件有冲突。假设它们是foo.cbar.c

运行git log master..B -- foo.c bar.c,并获取一组涉及foo.cbar.c的提交。

运行git log B..master -- foo.c bar.c,并获取另一组提交。

通过提交消息和补丁比较这两个集合,找到第一个集合中的依赖提交,排除那些在第二个集合中具有等效提交的提交。逐个挑选你真正需要的提交。

真实情况可能更加复杂。A和B可能是同一个错误的相关提交。只选取A或者只选取B不会产生冲突,但是如果你不选择两者,错误将无法修复。
如果你制定了良好的工作流程,例如将所有相关提交压缩成一个,并且在最开始的时候跟踪每个错误/功能与提交,你可以节省很多时间和精力。比起搜索缺失的依赖提交,逐个选取提交或一个压缩的提交要容易得多。可能会有冲突,但你可以确信这不是因为缺少某些依赖提交。

0

您可以解析差异以查找旧版本中所有更改的区域,然后使用 git log -L<start>,<end>:file... (*) 搜索已触及此代码的提交。因此,对于任何给定的提交,您都可以搜索它所依赖的较早提交。

但是,我不确定是否可能按照您想要的方式正确定义图形,因为关系“补丁B依赖于补丁A”并不那么规则。例如,可以创建连续的提交A-B-C-D,以便D将依赖于A和C,但不依赖于B,而C将依赖于B,但不依赖于A。那么您将如何绘制图形呢?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接