我如何知道在Git提交中发生了什么,两个父项没有合并到第二个父项的更改中?

我如何知道在Git提交中发生了什么,两个父项没有合并到第二个父项的更改中?,git,git-merge,git-commit,git-pull,git-log,Git,Git Merge,Git Commit,Git Pull,Git Log,在Gitk中,我可以看到一个团队成员的提交(X)有两个父级,第一个父级是他自己以前的提交(a),另一个父级包含许多其他人提交(1到5)。在他的合并之后,其他人(1到5以及其他人)所做的所有更改都不再出现在X、B、C等位置 A------------ \ X - B - C / 1--2--3--4--5 / e--r--j--k / l--m 如果我将提交X与提交A区分开来,

在Gitk中,我可以看到一个团队成员的提交(X)有两个父级,第一个父级是他自己以前的提交(a),另一个父级包含许多其他人提交(1到5)。在他的合并之后,其他人(1到5以及其他人)所做的所有更改都不再出现在X、B、C等位置

A------------
              \
               X - B - C 
              /
1--2--3--4--5
           /
e--r--j--k
     /
l--m
如果我将提交X与提交A区分开来,则不会显示任何差异;如果我将提交X与提交5区分开来,则会显示所有缺失的更改。此外,在提交X、B或C时,git日志不会显示在提交1到5中对文件所做的更改。但是,如果我使用git log——完整历史记录,那么历史记录确实会显示在1到5中所做的更改,但是这些更改在实际文件中并不存在,历史记录也不会显示这些更改正在被撤消。所以git日志——完整的历史记录似乎与当前文件内容相矛盾

我与提交X的用户进行了交谈。他说他没有进行重置或重新设置基础,他说在所讨论的时间内他没有恢复任何提交。然而,他说,他有时确实会做一个pull-originmaster,这会导致其他人的更改被放入他的索引或工作树中,就好像他做了这些更改,而不是这些更改的实际作者一样。他说,当这种情况发生时,他会做一个新的克隆人,不会把本地回购协议中的任何内容推给master,因为他认为Git做了错事

这两件事相关吗(坏拉和坏合并)

我怎样才能准确地说出发生了什么,以便我们在将来避免这种情况


是什么导致Git有时将从原始主机中提取的更改放在本地工作目录或索引中,就好像它们是本地更改一样?

有几种方法可以获取索引中的内容的行为。拉取是提取,然后是合并。这种合并可能会导致与您描述的索引中其他人的更改发生冲突。不了解冲突管理的用户可能会造成很大的损害,其结果可能是错误的合并

否则,他们必须将额外的标志传递给git pull,比如
--no commit
,以使其按照他们描述的方式运行

以下是我将如何调查

用户因没有报告所有信息而臭名昭著。我会找出问题发生时他们在做什么,让他们在问题发生时复制他们的终端历史记录。他们的shell历史或reflog可能也很有趣

检查它们的配置。我会看看他们的
~/.gitconfig
project/.git/config
env | grepgit
,看看有没有什么有趣的地方

我还想知道,如果他们在命令行上使用git或其他工具,该工具可能会导致问题

了解他们使用的git版本,可能是一个旧版本或错误版本(尽管我还没有遇到git错误导致的情况)

检查他们的遥控器,他们可能不知怎么混入了其他存储库

存储库是否有任何挂钩?如果是这样的话,他们使用的实用程序在用户的机器上可能无法正常工作吗

然而,他说,他有时确实会做一个pull-originmaster,这会导致其他人的更改被放入他的索引或工作树中,就好像他做了这些更改,而不是这些更改的实际作者一样

听起来他好像遇到了合并冲突,但不明白它们是什么。这是一个非常常见的问题,不幸的是,我们不知道如何避免它(例如,切换回SVN并不能避免它)

这到底是怎么发生的? 让我们打电话给您的开发人员Alice和Bob。Alice进行了1-5次提交,Bob进行了A和X次提交。下面是一段合理的历史

  • 鲍勃做了一个承诺

  • Alice进行提交1-5,并将其推送到中央存储库

  • Bob试图推送一个,但无法,因为他的存储库已过时

    $ git push
     ! [rejected]        master -> master (non-fast-forward)
    
  • 鲍勃,然后他按照你告诉他的做:他先拉。然而,他得到了一个合并冲突,因为commit a和commits 1-5接触了一些相同的代码

    $ git pull
    Auto-merging file.txt
    CONFLICT (content): Merge conflict in file.txt
    Automatic merge failed; fix conflicts and then commit the result.
    
  • Bob在他的工作目录中看到了其他人的更改,不明白为什么会有这些更改

    $ git status
        both modified:   file.txt
    
  • 他认为Git做错了什么,而事实上,Git要求他解决合并冲突。他试图签出新副本,但出现错误:

    $ git checkout HEAD file.txt  
    error: path 'file.txt' is unmerged
    
  • 由于它不起作用,他尝试
    -f

    $ git checkout -f HEAD file.txt
    warning: path 'file.txt' is unmerged
    
  • 成功!他承诺并推动

    $ git commit
    $ git push
    
  • 更难的部分 有很多git工具。认真地VisualStudio和Xcode都带有Git集成,还有其他几个GUI,甚至还有多个命令行客户机。人们描述如何使用Git的方式也很马虎,大多数开发人员对Git在“pull-commit-push”工作流之外的工作方式也不太熟悉

    不久前,有一篇关于这个主题的优秀论文(我很难找到)。一些结论是(请原谅我的记忆):

    • 除了一些非常简单的命令(commit、push),大多数开发人员并不知道如何使用源代码管理

    • 当源代码管理的行为不符合开发人员的预期时,他们会采取一些策略,例如复制粘贴一些他们不太了解的命令来“修复问题”、添加
      -f
      标志,或者删除存储库并重新开始使用干净的副本

    • 在开发团队中,通常只有首席开发人员真正知道回购协议中发生了什么

    所以这确实是一个教育挑战

    我认为Bob需要学习的关键经验是,
    git pull
    实际上就是
    git fetch
    git merge