这是gitk当前在我们的一个项目中的样子:
https://dl.dropbox.com/u/2582508/gitk.png
据我们所知,这显然是在使用远程分支完成一次“ git merge”之后发生的-我们不确定为什么或发生了什么。知道这里发生了什么吗?
更重要的是,修复它的最佳方法是什么?这些合并提交为空,但是当执行“ git rebase -i”时,合并提交通常似乎不会出现。
最重要的是,我希望不要使历史与其他克隆不兼容,即它们仍应能够拉/推/合并。那有可能吗?
最佳答案
这是某人使用git pull
(或等效地,git fetch
和git merge
)更新其项目的结果。假设您的存储库如下所示:
o --- o --- o [来源/管理员]
\
A --- B --- C [master]
也就是说,您已经在原始存储库中进行了A
,B
和C
的提交。
同时,还有其他一些更改并推送到共享存储库。如果然后运行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
的状态不同于F
和C
,因此必须将其区别对待。
现在,如果您进行此更改,您将获得:
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/