Git 合并冲突阻止从 newbs 中删除

Git merge conflict prevent deletes from newbs

我一直在寻求这方面的帮助,但我觉得我总是听到的答案总是把责任推给用户。这个问题几乎感觉像是 git 本身的错误。为什么git竟然允许这种情况发生?

情况是这样的。在合并冲突期间,没有冲突的文件正确地结束在暂存区中。必须处理有冲突的文件。

我有一些开发人员对 git 不够熟悉,无法意识到他们应该只处理冲突,而不是暂存区域中的其他文件。新手 git 用户的思维过程是这样的。

"I don't recognize those files, those aren't my files, I'm going to remove these from the staging area and only commit the files that I know are mine."

结果是这个新手刚刚从源代码管理中删除了一堆文件。

除了我们经常进行的训练之外,是否有 git 钩子或其他策略可以用来防止这种情况发生。不幸的是,没有合并冲突挂钩,如果有的话,我可以创建一个脚本并分发,它会温和地提醒用户不要从暂存区删除文件。

你可能会说的拉取请求。对有经验的开发人员的拉取请求肯定会发现这类问题。好吧,我们使用 bitbucket 服务器,出于某种原因,拉取请求预览没有显示在这种情况下将被删除的所有文件。这与创建合并预览实际上有多复杂有关。

结果是糟糕的合并冲突解决从 master 中删除了一堆其他人的工作。我们会在数小时或数天后发现它。我们恢复原状,斥责有问题的开发者并祈祷它再也不会发生,但必须有更好的方法。

如有任何关于此类问题的建议,我们将不胜感激。

嗯,你的问题肯定是git流量问题。

我喜欢做的是与 git workflow 流程 (https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) 相关的事情,基本上一个功能分支一旦创建就永远不会 merged/rebased 除非明确告知这样做由 git 管理员 - 大部分时间是因为在主分支中进行了一些结构更改。

想象一个由 10 多个开发人员组成的团队,每个人都在从事一项特定任务。如果每个人每次都将主分支合并到特性中,您将面临您描述的问题,无法解决合并冲突。

git 工作流的概念是,你有一些主要开发人员知道每个人都在做什么,这将使功能分支在每个 sprint 结束时合并到主分支.大多数时候,他们将能够处理冲突,如果他们不能,他们可以联系负责代码的开发人员并与他们核实。

您可以使用本地 git 挂钩来检查合并提交期间工作集中的文件数量是否与您预期的数量(在一定误差范围内)有关。

这里是一个 pre-commit 挂钩的例子,它将检查工作集中的文件数量是否在被合并的分支更改的文件的一定百分比内。

#!/bin/sh

if [ -e ./.git/MERGE_HEAD ]
then
  echo This is a merge commit with conflicts. Checking to make sure the working set matches the merge diff.

  # This is the commit we are merging into our branch (probably master or origin/master)
  mergehead=$(cat .git/MERGE_HEAD)

  # This is the last commit on our branch
  orighead=$(cat .git/ORIG_HEAD)

  # This is the common ancestor to the merge head and orig head
  mergebase=$(git merge-base $mergehead $orighead)

  # Find all the changes between the common ancestor and the merge head
  linecountmerge=$(git diff-tree $mergebase $mergehead -r --name-only | wc -l)

  # Find all files in the working set and staging area but exclude untracked files
  # Remove files that start with a ' ' character as that represents unstaged files
  # Split Renamed files into 2 lines since diff-tree stores these separately as an Add and Delete
  linecountworking=$(git status -s -uno | egrep '^[^ ].*$' | sed 's/ -> /\r\n/g'  | wc -l)

  #Uncomment the following lines to produce these results to files for troubleshooting
  #git diff-tree $mergebase $mergehead -r --name-status | sort > .git/mergediff.txt
  #git status -s -uno | egrep '^[^ ].*$' | sed 's/^R/D/g;s/ -> /\r\nA  /g;s/\"//g;s/  /\t/g' | sort > .git/workingset.txt

  echo Found $linecountmerge files in the merge diff.
  echo Found $linecountworking files in the working set.

  percentage=$(($linecountworking*100/$linecountmerge))

  minimumallowedpercentage=60

  echo Working set file count is $percentage% of the merge diff file count.

  if [ $percentage -lt $minimumallowedpercentage ]
  then
    echo
    echo
    echo !!! Working set file count is less than $minimumallowedpercentage% of the merge diff file count. !!!
    echo This probably means that you removed files from the working set during a merge conflict, which is a BAD THING!
    echo If you are SURE you still want to commit the changes, you will need to add --no-verify to the commit command.
    echo
    echo Merge commit aborted.
    exit 1
  fi
fi

此方法将要求您让所有开发人员在他们的本地存储库中安装此挂钩。