找到git commit的直接祖先(parent?)

时间:2017-03-01 12:24:27

标签: git github cherry-pick

启动一个新的repo并添加一些提交:

#( 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'

然而,我可以从1b7f299c中挑选4680089c7而没有任何冲突,即使它不是git日志中的一级后代:

#( 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 个答案:

答案 0 :(得分: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可能是同一个bug的相关提交。只选择A或只选择B会导致没有冲突,但是如果你不挑选这两个错误就无法解决。

如果您创建了一个良好的工作流程,例如将所有相关提交压缩为一个,并在最开始时使用提交跟踪每个错误/功能,则可以节省大量时间和精力。找到记录并逐个挑选提交或压缩提交要比搜索缺少的依赖提交容易得多。可能存在冲突,但您可以确定这不是因为您错过了一些依赖项提交。

答案 1 :(得分:0)

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

但是,我不确定是否可以根据需要正确定义图形,因为“修补程序B依赖于修补程序A”的关系不是那么规律。例如,可以创建连续提交A-B-C-D,这样当D依赖于A和C而不依赖于B时,C依赖于B而不依赖于A.那么你将如何绘制图形呢?