Stack Overflow问题如何和/或为什么在Git中合并比在SVN中更好?是一个很好的问题,有一些很好的答案.然而,它们都没有显示一个简单的例子,其中Git中的合并比SVN更好.
关于这个问题将被重复关闭的可能性是什么
几点:
Gre*_*ill 22
从实际角度来看,由于我称之为"大爆炸合并"问题,合并传统上一直很"困难".假设开发人员一段时间以来一直在研究某些代码并且尚未提交他们的工作(也许开发人员习惯于在Subversion中工作trunk
,并且不会提交未完成的代码).当开发人员最终提交时,将会有很多更改汇总到一个提交中.对于想要将他们的工作与这个"大爆炸"提交合并的其他开发人员来说,VCS工具不会有足够的信息来了解第一个开发人员如何达到他们所提交的点,所以你只是得到"这是一个巨大的冲突在这整个功能中,去解决它".
在另一方面,通常的风格与Git和具有廉价的地方分支机构等DVCS工作,是定期提交.一旦你完成了一些非常有意义的工作,你就可以了.它不一定是完美的,但它应该是一个连贯的工作单元.当你回来的合并,你仍然有小的提交,历史,显示了如何从原始状态到了目前的状态.当DVCS去与其他人的工作合并这一点,它有什么变化时做了很多的更多信息,以及你最终得到更小和更少的冲突.
关键是你仍然可以通过在你完成一些事情之后制作一个大爆炸提交来与Git合并一个难题.Git鼓励你做出较小的提交(通过使它们尽可能无痛),这使得未来的合并变得更容易.
Ing*_*man 16
我只能告诉你一个小实验,Git并不比Subversion好(同样的问题).
我想知道这种情况:你从两个分支"mytest1"和"mytest2"开始,都是基于相同的提交.你有一个包含函数blub()的C文件.在分支mytest1中,您将"blub()"移动到文件中的不同位置并提交.在分支mytest2中,您修改blub()并提交.在分支mytest2上你尝试使用"git merge mytest1".
似乎给出了合并冲突.我希望Git会认识到"blub()"在mytest1中被移动,然后能够将mytest2中的修改与mytest1中的移动自动合并.但至少在我尝试时这并没有自动起作用......
因此,虽然我完全理解Git在跟踪已合并的内容和尚未合并的内容方面要好得多,但我也想知道是否存在Git优于SVN的"纯粹"合并案例...
现在因为这个问题已经困扰了我很长一段时间,我真的试图创建一个Git 更好的具体例子,而SVN中的合并失败了.
我在这里找到一个/sf/answers/174066371/,但这包括重命名,这里的问题是没有重命名的情况.
所以这是一个SVN示例,基本上尝试这个:
bob +-----r3----r5---r6---+
/ / \
anna / +-r2----r4----+--+ \
/ / \ \
trunk r1-+-------------------r7-- Conflict
Run Code Online (Sandbox Code Playgroud)
这里的想法是:
这是一个Bash脚本,它会产生这种冲突(使用SVN 1.6.17和SVN 1.7.9):
#!/bin/bash
cd /tmp
rm -rf rep2 wk2
svnadmin create rep2
svn co file:///tmp/rep2 wk2
cd wk2
mkdir trunk
mkdir branches
echo -e "A\nA\nB\nB" > trunk/f.txt
svn add trunk branches
svn commit -m "Initial file"
svn copy ^/trunk ^/branches/anna -m "Created branch anna"
svn copy ^/trunk ^/branches/bob -m "Created branch bob"
svn up
echo -e "A\nMA\nA\nB\nB" > branches/anna/f.txt
svn commit -m "anna added text"
echo -e "A\nMB\nA\nB\nMB\nB" > branches/bob/f.txt
svn commit -m "bob added text"
svn up
svn merge --accept postpone ^/branches/anna branches/bob
echo -e "A\nMAB\nA\nB\nMB\nB" > branches/bob/f.txt
svn resolved branches/bob/f.txt
svn commit -m "anna merged into bob with conflict"
svn up
svn merge --reintegrate ^/branches/anna trunk
svn commit -m "anna reintegrated into trunk"
svn up
svn merge --reintegrate --dry-run ^/branches/bob trunk
Run Code Online (Sandbox Code Playgroud)
最后一次"--Dry-run"告诉你,会有冲突.如果您首先尝试将Anna的重新融合并入Bob的分支,那么您也会遇到冲突; 所以如果你替换最后svn merge
用
svn merge ^/trunk branches/bob
Run Code Online (Sandbox Code Playgroud)
这也显示出冲突.
这与Git 1.7.9.5相同:
#!/bin/bash
cd /tmp
rm -rf rep2
mkdir rep2
cd rep2
git init .
echo -e "A\nA\nB\nB" > f.txt
git add f.txt
git commit -m "Initial file"
git branch anna
git branch bob
git checkout anna
echo -e "A\nMA\nA\nB\nB" > f.txt
git commit -a -m "anna added text"
git checkout bob
echo -e "A\nMB\nA\nB\nMB\nB" > f.txt
git commit -a -m "bob added text"
git merge anna
echo -e "A\nMAB\nA\nB\nMB\nB" > f.txt
git commit -a -m "anna merged into bob with conflict"
git checkout master
git merge anna
git merge bob
Run Code Online (Sandbox Code Playgroud)
f.txt的内容改变如下.
初始版本
A
A
B
B
Run Code Online (Sandbox Code Playgroud)
安娜的修改
A
MA
A
B
B
Run Code Online (Sandbox Code Playgroud)
鲍勃的修改
A
MB
A
B
MB
B
Run Code Online (Sandbox Code Playgroud)
安娜的分支合并到鲍勃的分支后
A
MAB
A
B
MB
B
Run Code Online (Sandbox Code Playgroud)
正如许多人已经指出的那样:问题是,颠覆不记得鲍勃已经解决了冲突.因此,当您尝试将Bob的分支合并到主干中时,您必须重新解决冲突.
Git完全不同.这里有一些图形表示git正在做什么
bob +--s1----s3------s4---+
/ / \
anna / +-s1----s2----+--+ \
/ / \ \
master s1-+-------------------s2----s4
Run Code Online (Sandbox Code Playgroud)
s1/s2/s3/s4是git工作目录的快照.
笔记:
这是"git ref-log"的输出,它显示了所有这些:
88807ab HEAD@{0}: merge bob: Fast-forward
346ce9f HEAD@{1}: merge anna: Fast-forward
15e91e2 HEAD@{2}: checkout: moving from bob to master
88807ab HEAD@{3}: commit (merge): anna merged into bob with conflict
83db5d7 HEAD@{4}: commit: bob added text
15e91e2 HEAD@{5}: checkout: moving from anna to bob
346ce9f HEAD@{6}: commit: anna added text
15e91e2 HEAD@{7}: checkout: moving from master to anna
15e91e2 HEAD@{8}: commit (initial): Initial file
Run Code Online (Sandbox Code Playgroud)
从这个可以看出:
使用"git cat-file HEAD @ {8} -p",您可以检查初始提交对象的完整详细信息.对于上面的例子,我得到了:
tree b634f7c9c819bb524524bcada067a22d1c33737f
author Ingo <***> 1475066831 +0200
committer Ingo <***> 1475066831 +0200
Initial file
Run Code Online (Sandbox Code Playgroud)
"tree"行标识此提交引用的快照s1(== b634f7c9c819bb524524bcada067a22d1c33737f).
如果我做"git cat-file HEAD @ {3} -p"我得到:
tree f8e16dfd2deb7b99e6c8c12d9fe39eda5fe677a3
parent 83db5d741678908d76dabb5fbb0100fb81484302
parent 346ce9fe2b613c8a41c47117b6f4e5a791555710
author Ingo <***> 1475066831 +0200
committer Ingo <***> 1475066831 +0200
anna merged into bob with conflict
Run Code Online (Sandbox Code Playgroud)
上面显示了提交对象,bob在合并anna的开发分支时创建的."tree"行再次引用创建的快照(此处为s3).另外请注意"父"行.以"parent 346ce9f"开头的第二个告诉git,当你试图将bob的开发分支合并到master分支时,bob的最后一次提交将anna的最后一次提交作为祖先.这就是为什么git知道将bob的开发分支合并到主分支是一个"快进"的原因.
我没有具体的例子,但任何类型的重复合并都很困难,特别是所谓的纵横交错.
a
/ \
b1 c1
|\ /|
| X |
|/ \|
b2 c2
Run Code Online (Sandbox Code Playgroud)
合并b2和c2
Subversion Wiki上的wiki页面描述了基于合并信息的不对称Subversion合并(带有'sync'和'reintegrate'方向)和基于合并跟踪的DVCS中的对称合并之间的差异,其中有一节" 与Criss-Cross Merge对称合并 "
归档时间: |
|
查看次数: |
8142 次 |
最近记录: |