8

在线性历史中,两个提交 A 和 B 可以具有以下三种状态之一:

  • A 和 B 是相同的提交
  • A 严格在 B 之前
  • B 严格在 A 之前

Git 的非线性历史允许四个附加选项

  • A 和 B 共享父母和孩子
  • A 和 B 共享一个父级,但没有一个子级
  • A和B共享一个孩子但没有父母
  • A和B不共享

我不确定如何在不使用移植点的情况下实现最后两个,但它可能会发生。

我不确定如何以一种简单的方式确定这种关系——目前我只能想到一个有点奇怪的rev-list解决方案,即单独测试每个案例:

[[ "$a" = "$b" ]] && echo "same"
git rev-list "$b" | grep -q "$a" && echo "a before b"
git rev-list "$a" | grep -q "$b" && echo "b before a"
cat <(git rev-list "$a") <(git rev-list "$b") | sort | uniq -cd | grep -q 2 && echo "A and B share parents"
cat <(git rev-list --children "$a") <(git rev-list --children "$b") | sort | uniq -cd | grep -q 2 && echo "A and B share children"

必须有一种更好的、更糟糕的方式来做到这一点,那是什么?

4

1 回答 1

7

检查父子关系很容易,使用git merge-base. 如果结果是您的一个提交,它是父级,另一个是子级。

我建议忽略提交没有共同祖先的情况。当然,这可能会发生,但我不知道有任何有效的用例。我的意思是,你正在为一个真正的项目解决一个真正的问题,我相信你可以假设这不会发生。顺便说一句,merge-base将退出并出现错误,这是合并基础不存在的唯一情况,因此您仍然可以检测到这种情况。

为提交找到孩子是不可能的。绝对的。你不能可靠地做到这一点。提交具有“父”引用,但没有“子”引用。rev-list --children做完全不同的事情,它与你想要什么无关。你必须改进你的问题。

我可以建议使用git branch --contains <commit>or git tag --contains <commit>which 只会列出您可以从中进行提交的那些分支/标签。

或者,您可以查看git for-each-ref这将允许您测试是否可以从您的任何分支/标签访问提交。

于 2013-06-13T17:42:46.713 回答