git - 奇怪的git merge 问题

标签 git git-rebase git-merge

这是gitk当前在我们的一个项目中的样子:

https://dl.dropbox.com/u/2582508/gitk.png

据我们所知,这显然是在使用远程分支完成一次“ git merge”之后发生的-我们不确定为什么或发生了什么。知道这里发生了什么吗?

更重要的是,修复它的最佳方法是什么?这些合并提交为空,但是当执行“ git rebase -i”时,合并提交通常似乎不会出现。

最重要的是,我希望不要使历史与其他克隆不兼容,即它们仍应能够拉/推/合并。那有可能吗?

最佳答案

这是某人使用git pull(或等效地,git fetchgit merge)更新其项目的结果。假设您的存储库如下所示:

o --- o --- o [来源/管理员]
\
A --- B --- C [master]


也就是说,您已经在原始存储库中进行了ABC的提交。

同时,还有其他一些更改并推送到共享存储库。如果然后运行git fetch,则存储库如下所示:

o --- o --- o --- D --- E --- F [来源/主文件]
\
A --- B --- C [master]


现在,如果您运行git merge(请记住:git pull只是git fetch后跟git merge)。您将拥有:

o --- o --- o --- D --- E --- F [来源/主文件]
\
A --- B --- C --- G [master]


假设一切顺利,G可能只是一个“愚蠢的”合并提交。从技术上讲,G的状态不同于FC,因此必须将其区别对待。

现在,如果您进行此更改,您将获得:

o --- o --- o --- D --- E --- F
\
A --- B --- C --- G [来源/主文件]


如果继续开发,您将获得:

o --- o --- o --- D --- E --- F
\
A --- B --- C --- G [来源/主文件]
\
H --- I --- J [master]


现在,如果您继续这样做(如果很多人继续这样做),您将最终得到一棵像您照片中的那棵树。这不是“错误”,但是许多人不喜欢它,因为这使开发历史很难遵循。

解决此问题的方法是教人们重新设定基础。变基将(如您所述)远程化无用的合并提交,并为您git提供更清晰的历史记录。在上述情况下,您将获得线性开发历史。这更容易遵循。但是,您需要知道,在重新设置基准之后,您需要重新构建并重新测试代码……仅仅因为容易合并的代码并不意味着结果正确。

如果您使用中央存储库来共享正式的开发线,则可以实现一个预接收钩子,该钩子检测这些自动(“愚蠢” /“无用”)合并提交并拒绝推送-迫使用户重新设置基础。实际上,您希望钩子查找默认的合并提交消息...因此,如果您确实确实想保留合并提交(有时很有意义),则至少必须编写一条智能的提交消息。

这是一个示例钩子。我剥离了很多多余的东西,所以我没有去测试。

#!/ bin / bash

#此脚本基于Gnome的pre-receive-check-policy钩子。
#此脚本*仅*检查多余的合并提交。

#用于某些消息
server = git.wherever.com

GIT_DIR = $(git rev-parse --git-dir 2> / dev / null)

in_import(){
测试-e“ $ GIT_DIR / pending”
}

强制(){
测试-n“ $ GNOME_GIT_FORCE”
}

check_commit(){
提交= $ 1

subject =“ $(git log $ commit -1 --pretty = format:%s)”
if expr“ $ subject”:“。*合并分支。* of。* \(git \ | ssh \):”> / dev / null 2>&1;然后
如果! in_import &&!被迫;然后
猫&2
---
提交:

紧急行动
git log $ commit -1>&2
猫&2

看起来它是通过不带--rebase键入'git pull'而产生的
您进行本地更改时的选项。现在运行'git pull --rebase'
将解决问题。然后,请再次尝试“ git push”。请参见:

http://live.gnome.org/Git/Help/ExtraMergeCommits
---
紧急行动
1号出口
科幻
科幻
}

check_ref_update(){
oldrev = $ 1
newrev = $ 2
refname = $ 3

change_type =更新
如果expr $ oldrev:“ ^ 0 \ + $”> / dev / null 2>&1;然后
change_type =创建
科幻

如果expr $ newrev:“ ^ 0 \ + $”> / dev / null 2>&1;然后
如果[x $ change_type = xcreate];然后
#删除无效的引用,允许
返回0
科幻
change_type =删除
科幻

案例$ refname在
裁判/负责人/ *)
#分支更新
branchname = $ {refname#refs / heads /}

范围=
#对于此分支更新中引入的新提交,我们希望
#运行一些检查以发现常见错误。

#此处的表达式与post-receive-notify-cia中的相同;我们采取
#回购中的所有分支,如“ ^ / ref / heads / branchname”,其他
#比我们实际上要提交的分支要多,并排除提交
#已经在以下之间的提交列表中的那些分支上
#$ oldrev和$ newrev。

如果[-n“ $ range”];然后
用于合并在$(git rev-parse --symbolic-full-name --not --branches | \
egrep -v“ ^ \ ^ $ refname $” | \
git rev-list --reverse --stdin“ $ range”);做
check_commit $合并
做完了
科幻
;;
埃萨克

返回0
}

如果[$#= 3];然后
check_ref_update $ @
其他
同时读取oldrev newrev refname;做
check_ref_update $ oldrev $ newrev $ refname
做完了
科幻

出口0

关于git - 奇怪的git merge 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2288836/

相关文章:

git - 当我使用 rebase 执行 git pull 时,如何禁用 rebase Hook ?

多个 0.5GB 二进制文件的 GIT Rebase Fatal

git - merge 没有 parent 的提交

git - 用 git 子模块替换了第三方代码,现在我不能切换分支

git - 为什么我们的 Git 存储库中缺少代码,可以通过 rebase 解决吗?

git - 如何从 Bitbucket 存储库推送到 Azure 存储库,不同的用户电子邮件

java - IntelliJ Git 集成插件 -> "New Branch"将大写 F 放入 "feature/abc"

ruby-on-rails - 使用 Chromebook 14 进行开发的建议

ruby-on-rails - 将数据和模式从开发 rails 迁移到生产 rails heroku

git rebase - 批量更改消息