为啥我在具有不同哈希的两个分支中有相同的提交

Posted

技术标签:

【中文标题】为啥我在具有不同哈希的两个分支中有相同的提交【英文标题】:Why do I have the same commits in two branches with different hashes为什么我在具有不同哈希的两个分支中有相同的提交 【发布时间】:2013-04-20 18:46:08 【问题描述】:

对此我有点疑惑……

我有两个分支,它们都有相同的提交系列。

真实的历史是,它们是由我的同事编写的,提交并推送到分支 A 的 github。在某个阶段,我将分支 A 与我的 B 分支合并。

git 现在似乎显示的是他在分支 A 中的提交,以及它们的哈希值,以及我的(发散的)分支中的相同提交,显示我作为作者,以及一组不同的哈希值,与我正在做的工作混合在我的分支上。

这感觉像是某种变基问题(我们有时都使用 GitHubForWindows,它会在同步过程中变基),但我不知道有人向我们报告了问题。

任何有关导致此问题的原因或如何解决问题的想法将不胜感激。

【问题讨论】:

cherry-pick被使用了吗? 在过去的某个时候,是的,但不是在这段历史中。 在我的情况下使用了cherry-pick,不同之处在于“提交日期” 【参考方案1】:

如果git rebase 是您工作流程的一部分,那么您所描述的内容很常见。例如:

$ git log --graph --oneline --all
* 76af430 fc           # branch: foo
| * 7c495ad mb         # branch: bar, master
|/  
* 74cbb35 a

$ git rebase foo       # while on branch master
First, rewinding head to replay your work on top of it...
Applying: mb

$ git log --graph --oneline --all
* 6810e67 mb           # branch: master
* 76af430 fc           # branch: foo
| * 7c495ad mb         # branch: bar
|/  
* 74cbb35 a

【讨论】:

谢谢,这就是导致我们出现上述情况的原因。因此,如果您将分支 X 重新设置为分支 Y,并且它具有来自另一个分支(不是 X 和 Y,而是另一个分支 X)的提交,它将创建不同的哈希(来自 X 上的那些)。为什么会这样?有没有办法在预变基挂钩中防止这种情况(意思是 - 确定这些不是“本机”提交)? 我无法重现 rebase 更改提交哈希 ID(或在何种情况下),因此我怀疑在我的情况下我可以使用cherry pick,它根据其定义重新生成哈希 ID - ***.com/questions/20698118/… 【参考方案2】:

您应该获得一些强大的工具(普通的 gitk 应该可以正常工作)并仔细检查匹配的(但哈希值不同)提交 - 查找 AuthorCommitterDate 字段中的差异。还要比较父提交的哈希,因为提交对象还记录其父提交的哈希,因此引用不同父 SHA-1 提交名称的相同提交将不同。

您还能否详细说明您的提交与您的同行创作的提交“混合”到什么程度?所有这些提交是形成线性历史还是存在合并点?

前者表示使用了变基。

根据目前可用的信息,我会这样做:

    停止使用“Github for Windows”,因为不费吹灰之力的解决方案往往会造成您现在面临的情况:当出现问题时,您不知道为什么会发生问题以及如何解决问题。

    获取“常规”Git for Windows(如果您想要不试图智取用户的精美 GUI,则可能是 Git Extensions)。

    通过分叉另一个分支来保存您当前的功能分支。

    (硬)将您的功能分支重置为您的同行。

    Cherry-pick您从您保存的分支中从最旧到最新的更改。

    这可能会产生冲突(因为这些提交将被植入它们最初创建的不同代码状态)。

在结果中,您将拥有一个没有“虚假相同”提交的分支。

那么您和您的同行都应该阅读合并和变基工作流程,采用其中一种,然后在处理功能分支时,明智地进行合并和/或变基,了解您为什么'正在这样做,结果会发生什么。我建议您不要盲目依赖工具来做正确的事™。

【讨论】:

我几乎不将 Github 用于 windows - 所有分支、合并推送和拉取以及我通过 poshgit shell 进行的大多数提交。大多数情况下,我首先使用它来设置身份验证,在正确的文件夹中打开 shell,并查看基本历史记录。但是,该项目的其他人对它有更多的依赖。我们做了樱桃挑选和硬重置。排序。谢谢。 谢谢你——对我来说,(唯一的)区别在于“提交日期”【参考方案3】:

在对两个串联的分支进行变基后,我遇到了这个“git diff diff”问题。相同的提交被应用于相同的分叉点,所以我很困惑地看到分支分歧。甚至 patch-id 也是一样的。

查看原始差异发现差异在于“提交者时间”:

$ diff <(git show --format=raw $COMMIT1) \
       <(git show --format=raw $COMMIT2)
1c1
< commit $COMMIT1
---
> commit $COMMIT2
5c5
< committer $ME <me@work.com> 1470128045 +0200
---
> committer $ME <me@work.com> 1470129095 +0200

在 git rebase 上使用 --committer-date-is-author-date 重做 rebase 修复了一些分歧,但不是全部。 (我不知道为什么..?我认为分歧发生在第一次重新合并时)

然后我将 filter-branch 用作大锤:

git filter-branch --env-filter \
'export GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE'\
origin/master..HEAD

这足以使系列保持一致:

$ git show --format=raw HEAD | egrep 'author|committer'
author $ME <me@work.com> 1470065063 +0200
committer $ME <me@work.com> 1470065063 +0200

【讨论】:

比较几乎相同的提交的更好的命令:gitshow="git show --color --format=fuller" ; diff -u &lt;($gitshow $commit1) &lt;($gitshow $commit2) | less -R 通过这个命令,我们有可读的 CommitDate(可以不同)和颜色差异。【参考方案4】:

我有来自远程和本地分支的相同提交,具有不同的哈希 id。 看来git pull --rebase 解决了我的问题。

【讨论】:

我无法重现 rebase 更改提交哈希 ID(或在何种情况下),因此我怀疑在我的情况下我可以使用cherry pick,它根据其定义重新生成哈希 ID - ***.com/questions/20698118/…

以上是关于为啥我在具有不同哈希的两个分支中有相同的提交的主要内容,如果未能解决你的问题,请参考以下文章

为啥当我在 MD5 哈希中转换相同的 C++ 字符串时,每次都会获得不同的输出?

Django-检查两个密码哈希是否具有相同的原始密码

Django中相同形式的两个不同提交按钮

具有相同哈希码的两个不相等对象

为啥 Gatsby 的两个不同布局上的两个 StaticQuery 元素不能具有相同的名称?

在 Perl 中测试两个哈希键是不是具有相同的结构