58

Stack Overflow question How and/or why is merging in Git better than in SVN? is a great question with some great answers. However none of them show a simple example where merging in Git works better than SVN.

On the chance this question will be closed as a duplicate, what is

  1. A concrete merge scenario
  2. How it is difficult in SVN?
  3. How the same merge is easier in Git?

A few points:

  • No philosophy or deep explanations of what a DVCS is please. These are great, really, but I don't want their details to obfuscate the answer to this (IMHO) important
  • I don't care about "historic SVN" at the moment. Please compare modern Git (1.7.5) to modern SVN (1.6.15).
  • No renames please - I know that Git detects renames and moves, while SVN doesn't. This is great, but I am looking for something deeper, and example that doesn't involve renames or moves.
  • No rebase or other 'advanced' Git operation. Just show me the merge please.
Community
  • 1
  • 1
ripper234
  • 222,824
  • 274
  • 634
  • 905
  • @suravi - I'm not talking about local branching at all, nor performance. I want to understand why/if there are less _merge conflicts_ in git than svn. – ripper234 May 30 '11 at 03:48
  • You mean http://stackoverflow.com/questions/2475831/merging-hg-git-vs-svn didn't answer your current question? (or http://stackoverflow.com/q/459891/6309 ?) – VonC May 30 '11 at 04:04
  • (or http://stackoverflow.com/questions/2518779/what-are-the-benefits-of-mercurial-or-git-over-svn-for-branching-merging/2553558#2553558 or http://stackoverflow.com/questions/2544008/what-are-the-differences-between-git-and-svn-when-it-comes-to-merge-conflicts-sol/2668034#2668034) ... etc – VonC May 30 '11 at 04:12
  • @VonC - thanks. While most of the answers you linked to weren't what I'm looking for, this one seems to be a valid example: http://stackoverflow.com/questions/459891/what-makes-some-version-control-systems-better-at-merging/462389#462389 – ripper234 May 30 '11 at 04:17
  • @ripper234: you mean that http://stackoverflow.com/questions/2475831/merging-hg-git-vs-svn/2486662#2486662 isn't an actual detailed "show me the merge already" example??? Or http://stackoverflow.com/questions/2544008/what-are-the-differences-between-git-and-svn-when-it-comes-to-merge-conflicts-sol/2668034#2668034? – VonC May 30 '11 at 04:21
  • @VonC - however, the more common example is @Greg's answer ... now I just need a concrete a example of that. http://stackoverflow.com/questions/6172037/really-an-example-that-merging-in-git-is-easier-than-svn/6172181#6172181 – ripper234 May 30 '11 at 04:21
  • @VonC - I updated my answer a few mins ago to exclude renames/moves. I know git simply does these better by design (or an svn design flaw), but I want to find the examples not related to renames that it also does better ... check out Greg's answer. – ripper234 May 30 '11 at 04:22
  • Frankly, the simple fact that you can move a directory directly from the OS without screwing up SVN because you did move `.svn` around is enough for most developers to switch to a DVCS in a hurry ;) – VonC May 30 '11 at 04:26
  • @VonC - git has many advantages, see also http://stackoverflow.com/questions/871/why-is-git-better-than-subversion I'm just frustrated that I always heard how git is better at merging, and saw some examples related to renames, but I feel I'm still missing a good simple "core" example without any merges. – ripper234 May 30 '11 at 04:28
  • @ripper234 If http://stackoverflow.com/questions/459891/what-makes-some-version-control-systems-better-at-merging/462389#462389 is a valid example why not post it as the answer to your question and accept it? – urig May 30 '11 at 09:41
  • @urig - it's one valid example, but it's not that mainstream. I'm actually much more interested in @Greg's answer to this question, because this is the argument I always heard ... we just need to hack it a bit to find the concrete canonical example once and for all. – ripper234 May 30 '11 at 12:58
  • Nice question. In my opinion the merging powers of git are usually overpraised :) And I've just faced another queer behavior of git, which is unable to do an automatic merge on the same branch - see [the question](http://stackoverflow.com/questions/11223353/why-doesnt-git-merge-the-conflict-free-changes-automatically-in-some-cases). – AntonK Jun 27 '12 at 09:54

7 Answers7

23

From a practical perspective, merging has traditionally been "hard" because of what I call the "big bang merge" problem. Suppose a developer has been working away on some code for a while and hasn't committed their work yet (maybe the developer is accustomed to working in Subversion against trunk, and doesn't commit unfinished code). When the developer finally commits, there is going to be a lot of changes all rolled up into one commit. For the other developers who want to merge their work with this "big bang" commit, the VCS tool isn't going to have enough information about how the first developer got to the point they committed, so you just get "here's a giant conflict in this whole function, go fix it".

On the other hand, the usual style of working with Git and other DVCS that have cheap local branches, is to commit regularly. Once you've done one bit of work that pretty much makes sense, you commit it. It doesn't have to be perfect but it should be a coherent unit of work. When you come back to merge, you still have that history of smaller commits that shows how you got from the original state to the current state. When the DVCS goes to merge this with the work of others, it has a lot more information about what changes were made when, and you end up getting smaller and fewer conflicts.

The point is that you can still make merging a hard problem with Git by making a single big bang commit only after you've finished something. Git encourages you to make smaller commits (by making them as painless as possible), which makes future merging easier.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • This is a great motivation, and I've heard these arguments before and believe they are correct. Have you encountered a concrete example that illustrates this? – ripper234 May 30 '11 at 04:20
  • 3
    Perhaps it is true in Darcs, but it is not true in Git, because Git for merging considers in usual case only three versions: ours, theirs and ancestor (merge base). – Jakub Narębski May 30 '11 at 15:21
  • Just FYI - if you/someone distills this use case into a concrete example, I'll accept their answer, because I believe this is the quintessential example. – ripper234 May 31 '11 at 06:41
  • 9
    With Subversion, I use feature branches for what git has local branches. So many people say that you can't commit unfinished work in Subversion - but it's just not true. I can do the same thing with Subversion every day and it's not more expensive. I don't see any advantage here considering the merge. – Wolfgang Jul 27 '11 at 19:35
  • Cheating detected. Shown scenario isn't a problem of Subversion per se, but only "Monkey with grenade" case – Lazy Badger Dec 21 '12 at 17:33
  • @LazyBadger I like the "monkey with grenade" expression, but I think it's invalid here. The question is whether one (Git) is easier than the other (SVN) on the topic of merging. It makes perfect sense that one tests a few different scenarios (extremes/commons/rare) to make the overall case. It's entirely likely that merging is identical in the "commit every hour" case but easier, using Git, where committing happens more often. The question asks for a concrete scenario - you seem to be insisting the scenario must be "typical" - the question doesn't and there's no reason to limit it. – PandaWood Jan 23 '13 at 23:13
17

I can only tell you of a small experiment were Git was NOT better than Subversion (same problems).

I was wondering about this case: You start with two branches "mytest1" and "mytest2" both based on the same commit. You have got a C file which contains a function blub(). In branch mytest1 you move "blub()" to a different position in the file and commit. In branch mytest2 you modify blub() and commit. On branch mytest2 you try to use "git merge mytest1".

Seems to give a merge conflict. I hoped that Git would recognize that "blub()" was moved in mytest1 and then be able to auto-merge the modification in mytest2 with the move in mytest1. But at least when I tried this did not work automatically...

So while I fully understand that Git is much better at tracking what has been merged and what has not been merged yet, I also wonder if there is "pure" merge case in which Git is better than SVN...

Now because this question has been bugging me for a long time I was really trying to create a concrete example where Git is better, whereas merging in SVN fails.

I found one here https://stackoverflow.com/a/2486662/1917520, but this includes a rename and the question here was for a case without a rename.

So here is an SVN example which basically tries this:

bob        +-----r3----r5---r6---+
          /                /      \
anna     /  +-r2----r4----+--+     \
        /  /                  \     \
trunk  r1-+-------------------r7-- Conflict

The idea here is:

  • Anna and Bob are both developers with their own branches (created in r2,r3).
  • Anna does some modifications (r4),
  • Bob does some modifications (r5).
  • Bob merges the modifications from Anna into his branch; this gives conflicts, which Bob fixes and then commits (r6).
  • Annas modifications are merged back into the trunk (r7).
  • Bob tries to merge his modification back into the trunk and this again gives a conflict.

Here is a Bash script, which produces this conflict (using SVN 1.6.17 and also 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

The last "--dry-run" tells you, that there will be a conflict. If you instead first try to merge Anna's reintegration into Bob's branch then you also get a conflict; so if you replace the last svn merge with

svn merge ^/trunk branches/bob

this also shows a conflicts.

Here is the same with 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

The contents of f.txt change like this.

Initial version

A
A
B
B

Anna's modifications

A
MA
A
B
B

Bob's modifications

A
MB
A
B
MB
B

After Anna's branch is merged into Bob's branch

A
MAB
A
B
MB
B

As so many people already pointed out: The problem is, that subversion cannot remember that Bob already resolved a conflict. So when you try to now merge Bob's branch into the trunk, then you have to re-resolve the conflict.

Git works completely different. Here some graphical representation what git is doing

bob         +--s1----s3------s4---+
           /                /      \
anna      /  +-s1----s2----+--+     \
         /  /                  \     \
master  s1-+-------------------s2----s4

s1/s2/s3/s4 are the snapshots of the working directory git takes.

Notes:

  • When anna and bob create their development branches, this will NOT create any commits under git. git will just remember that both branches initially refer to the same commit object as the master branch. (This commit in turn will refer to the s1 snapshot).
  • When anna implements her modification, this will create a new snapshot "s2" + a commit object. A commit object includes:
    • A reference to the snapshot (s2 here)
    • A commit message
    • Information about ancestors (other commit objects)
  • When bob implements his modification, this will create another snapshot s3 + a commit object
  • When bob merges annas modifications into his development branch this will create yet another snapshot s4 (containing a merge of his changes and anna's changes) + yet another commit object
  • When anna merges her changes back into the master branch, this will be a "fast-forward" merge in the shown example, because the master has not changed in the meantime. What "fast-forward" here means is, that the master will simply point to the s2 snapshot from anna without merging anything. With such a "fast-forward" there will not even be another commit object. The "master" branch will just directly now refer to the last commit from the "anna" branch
  • When bob now merges his changes into the trunk, the following will happen:
    • git will find out that the commit from anna which created the s2 snapshot is a (direct) ancestor for bobs commit, which created the s4 snapshot.
    • because of this git will again "fast-forward" the master branch to the last commit of the "bob" branch.
    • again this will not even create a new commit object. The "master" branch will simply be pointed to the last commit of the "bob" branch.

Here is the output of "git ref-log" which shows all of this:

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

As you can see from this:

  • when we go to anna's development branch (HEAD@{7}) we do not change to a different commit, we keep the commit; git just remembers that we are now on a different branch
  • At HEAD@{5} we move to bob's initial branch; this will move the working copy to the same state as the master branch, because bob has not changed anything yet
  • At HEAD@{2} we move back to the master branch, so to the same commit object everything started from.
  • Head@{1},HEAD@{0} show the "fast-forward" merges, which do not create new commit objects.

With "git cat-file HEAD@{8} -p" you can inspect the complete details of the initial commit object. For the example above, I got:

tree b634f7c9c819bb524524bcada067a22d1c33737f
author Ingo <***> 1475066831 +0200
committer Ingo <***> 1475066831 +0200

Initial file

The "tree" line identifies the snapshot s1 (==b634f7c9c819bb524524bcada067a22d1c33737f) to which this commit refers.

If I do "git cat-file HEAD@{3} -p" I get:

tree f8e16dfd2deb7b99e6c8c12d9fe39eda5fe677a3
parent 83db5d741678908d76dabb5fbb0100fb81484302
parent 346ce9fe2b613c8a41c47117b6f4e5a791555710
author Ingo <***> 1475066831 +0200
committer Ingo <***> 1475066831 +0200

anna merged into bob with conflict

This above shows the commit object, bob created when merging anna's development branch. Again the "tree" line refers to the created snapshot (s3 here). Additionally note the "parent" lines. The second one which starts with "parent 346ce9f" later tells git, when you try to merge back bob's development branch into the master branch, that this last commit of bob has anna's last commit as an ancestor. This is why git knows that the merge of bob's development branch into the master branch is a "fast-forward".

Community
  • 1
  • 1
Ingo Blackman
  • 991
  • 8
  • 13
  • 1
    Wait. Why does this demonstrate Subversion is better than Git for this workflow? I think Git's behavior is preferred, since it simply detects Bob already resolved the conflict (really, recorded how to resolve the conflict), and fast-forwards the commit. The real question is what happens when Anna wants to merge her changes back into trunk, not realizing Bob's already integrated her changes and then some. Git still tells Anna there is a conflict, which is important. – John Zabroski Jun 11 '13 at 01:59
  • 2
    OK my answer might be confusing: The first part refers to an experiment on pure merging where git + svn are the same (in one branch you move a function, in another branch you modify a function, when you merge git + svn both give a conflict). The **second** part (what you refer to) actually answers the posed question: It gives an example where git is definitely better than svn. So yes: the 2nd part of the answer demonstrates a case where git is better. – Ingo Blackman Jun 12 '13 at 00:34
  • Ah, thanks. I must have misread that important line. Was up late. Just a quick observation. Block move detection is really a result of the differencing engine, not the version control system, per se. You can always build a smarter conflict resolver on top of your VCS, but Git doesn't by default because it tries to remain language neutral. git blame -CCC does this. – John Zabroski Jun 12 '13 at 03:48
  • Oh, I did not know about the "-CCC" switch; nice :-). I am aware that this is purely the conflict resolver, but I was wondering if that conflict resolver in git was better than the one in svn. To be language neutral: I am not sure; if you really had an exact move (no other modifications at all) of a text block (in my example a function), and someone else modifies this said text block, wouldn't that still be language neutral ? I haven't thought about this too much; maybe there really are cases where this might be the wrong auto-resolution policy... – Ingo Blackman Jun 13 '13 at 01:10
  • git is superior to svn because svn uses snapshots, and git uses changesets. They are not mathematically equivalent representations. It is the difference between an integral and its derivative. Please see the short 2 page essay "Integrals and Derivatives" by Martin Pool, creator of the bzr dvcs: http://sourcefrog.net/weblog/software/vc/derivatives.html Everything else is the tools on top of the system, like the differencing engine, which feeds into the conflict resolver. – John Zabroski Jun 13 '13 at 04:08
  • 1
    Technically, it is possible for a changeset-oriented system to have a worse or "just as worse/good" conflict resolver than a snapshot-oriented system. This is what makes the difference between the two so difficult to see, because we tend to think concretely using examples and cannot always easily abstract away to generalities. For historical reference, see this thread from 2005: http://www.gelato.unsw.edu.au/archives/git/0504/2279.html – John Zabroski Jun 13 '13 at 04:20
  • After now having learned a lot more about git I have to comment. git actually uses snapshots (not changesets). The real difference is, that git remembers the relation of the snapshots (which snapshot was created from which other snapshot(s)). This information is missing in subversion, or to be precise with recent subversion the information is by far less complete than it is in git. That is why git has an easier time to find out how a snapshot evolved and that is why it has a better idea how to merge different snapshots... – Ingo Blackman Jan 25 '14 at 22:26
  • What is your source? All of the main operations in git (and every distributed version control system, essentially) use changesets as the data structure. Svn, by contrast, uses snapshots. So, while Svn 1.8 has built some stuff under the hood to track the relations and while Git has built some stuff under the hood to track the snapshots, conceptually working with changesets is fundamentally more powerful. My best source for this argument is Martin Pool's seminal essay "Integrals and Derivatives" (Martin is the author of bzr). http://sourcefrog.net/weblog/software/vc/derivatives.html – John Zabroski Jan 27 '14 at 01:18
  • Note, toward the end of Martin's article, he discusses converting between representations. I take some offense to his characterization of calculus as a step beyond algebra, though. Most of my undergrad was spent teaching calculus as a TA, and the real skinny there is that there are key concepts students must learn in calculus to move onward. For example, it is well-known in education literature on calculus that understanding what a limit is, and what it means to "take a limit", is a "threshold concept." – John Zabroski Jan 27 '14 at 01:23
  • That said, thinking harder about your statement, I think your confusion may come from the fact that git stores changesets *chronologically*. So does Mercurial and bzr. Darcs is a distributed vcs that simply works with patches, independent of chronological order. See: http://darcs.net/DifferencesFromOtherDVCS – John Zabroski Jan 27 '14 at 01:39
  • Also, taking this thread of discussion to its logical conclusion, you will note the darcs link explains why the differencing engine in darcs is theoretically more powerful than git's because it removes the chronological ordering constraint on the math problem. Less constraints, more power (generally). – John Zabroski Jan 27 '14 at 01:49
  • Urghs: I haven't looked too long into this thread. Why did I say git uses "snapshots". Because this is just what git does. My source is simply the source code of git and understanding what it does. When you refer to a commit with its SHA1 checksum, you basically tell git that you refer to a particular snapshot of the whole working directory. If you diff two SHA1 checksums, then git will calculate the diff out of the two snapshots you give to it (of course the way git handles this, means that it will find out VERY fast if two files differ at all). So no changesets in git; just snapshots. – Ingo Blackman Apr 20 '16 at 16:50
6

I don't have concrete examples, but any kind of repeated merge is difficult, in particular so called criss-cross merge.

   a
  / \
 b1  c1
 |\ /|
 | X |
 |/ \|
 b2  c2

merging b2 and c2


The wiki page on Subversion Wiki describing differences between mergeinfo based assymetric Subversion merge (with 'sync' and 'reintegrate' directions) and merge tracking based symmetric merge in DVCS has a section "Symmetric Merge with Criss-Cross Merge"

Jakub Narębski
  • 309,089
  • 65
  • 217
  • 230
  • This seems concrete enough to me! It happens all the time in large teams with less rigorous workflows: everyone hacks away, and periodically pulls from the central repo or from another developer who coded the thing they need. – Cascabel May 30 '11 at 18:43
  • WTF? b2 == c2 - merge not needed. Lie detected – Lazy Badger Dec 21 '12 at 17:35
  • @LazyBadger: First, merge might be evil, or just resolve conflicts differently. Second, the ---- line might be a series of non-merge revisions, not shown to make graph simpler. – Jakub Narębski Dec 23 '12 at 13:21
  • "merge might be evil" - is just useless zero-value wording. **SHOW ME THIS EVIL!**. Second workflow I use most time in long-live feature-branches for data-exchange without big troubles - "Merge often!!!" – Lazy Badger Dec 23 '12 at 13:44
  • 1
    @LazyBadger: I am sorry for using jargon without explanation: **evil merge** is a merge commit where some lines does not come from either one or the second parent (branch merged into or branch being merged). – Jakub Narębski Dec 25 '12 at 11:06
  • @LazyBadger: That is what I wrote: "I don't have concrete examples, but any kind of repeated merge is difficult, in particular so called criss-cross merge." What I know is that the *recursive merge* algorithm in git was created to deal with this and similar examples. I **don't know** if SVN merge algorithm, based on copyfrom and merge(d)info properties can deal with this situation. – Jakub Narębski Dec 25 '12 at 21:00
4

The most concrete example I can think of is the simplest merge that does not result in merge conflicts. However (TL;DR) with that example Git is still inherently a simpler procedure than with Subversion. Lets review why:

Subversion

Consider the following scenario in subversion; the trunk and the feature branch:

   1  2  3
…--o--o--o              trunk
          \4  5
           o--o         branches/feature_1

To merge you can use the following command in subversion:

# thank goodness for the addition of the --reintegrate flag in SVN 1.5, eh?
svn merge --reintegrate central/repo/path/to/branches/feature_1

# build, test, and then... commit the merge
svn commit -m "Merged feature_1 into trunk!"

In subversion merging the changes requires another commit. This is to publish the changes that the merge did with applying the changes on the feature branch virtual directory back into the trunk. That way everyone working with the trunk can now use it and the revision graph looks like sort of like this:

   1  2  3      6
…--o--o--o------o       /trunk
          \4  5/
           o--o         /branches/feature_1

Lets see how this is done in git.

Git

In Git this merge commit is really not necessary as branches are glorified bookmarks on the revision graph. So with the same kind of revision graph structure it sort of looks like this:

         v-- master, HEAD

   1  2  3
…--o--o--o
          \4  5
           o--o

              ^-- feature_branch

With the head currently on the master branch we can perform a simple merge with the feature branch:

# Attempt a merge
git merge feature_branch

# build, test, and then... I am done with the merge

... and it will fast-forward the branch over to the commit where feature branch is pointing at. This is made possible because Git knows that the goal of the merge is a direct descendant and the current branch only needs to take in all the changes that happened. The revision graph will end up looking like this:

   1  2  3  4  5
…--o--o--o--o--o
               ^-- feature_branch, master, HEAD

The changes does not need a new commit as all git has done is to move the branch references further up to the front. All that is left is to publish this to the public repository if you have any:

# build, test, and then... just publish it
git push

Conclusion

Given this simple scenario you can assert two things in the difference between Subversion and Git:

  • SVN requires at least a couple of commands to finalize the merge and forces you to publish your merge as a commit.
  • Git only requires one command and does not force you to publish your merge.

Given this to be the most simplest merge scenario it is difficult to argue that subversion is easier than git.

In more difficult merge scenarios, git also provides you the ability to rebase the branch that produces a simpler revision graph at the cost of history rewriting. Once you get the hang of it though, and avoid publishing history rewrites of things already published, it isn't really that bad of a thing to do.

Interactive rebases is outside the scope of the question but to be honest; it enables you the ability to rearrange, squish and remove commits. I wouldn't willingly want to switch back to Subversion as history rewriting is not possible by design.

Spoike
  • 119,724
  • 44
  • 140
  • 158
2

Looks like it's a myth that merging in Git is easier than in SVN...

For example, Git cannot merge into a working tree that has changes, unlike SVN.

Consider the following simple scenario: you have some changes in your working tree and want to integrate remote changes without committing your own.

SVN: update, [resolve conflicts].

Git: stash, fetch, rebase, stash pop, [resolve conflicts], [stash drop if there were conflicts].

Or do you know an easier way in Git?


Btw, this use case seems to be so important that IntelliJ even implemented the missing "Update Project" functionality for Git (analogon to SVN update) which can automate the manual steps described above:

IntelliJ IDEA - Update Project

Eugen Labun
  • 2,561
  • 1
  • 22
  • 18
  • "Git cannot merge into a working tree that has changes, unlike SVN." Doing do with a system allowing for easy local commits would be stupid. You want to commit your local changes first, then apply the other. – Martin Scharrer Mar 22 '18 at 12:13
  • 2
    Hi Martin. No, I want first merge changes of coworkers into my working space to ensure that my changes are still properly working on top of them. How else can collaboration work? Unfortunately Git does not offer a simple way to achieve that. Don't see how local commits can help here. – Eugen Labun Mar 23 '18 at 18:12
  • 1
    @EugenLabun , git-way of doing such things is to create local branches, so the workflow is as follows: a) finish your part; b) commit locally (don't push); c) pull (which performs the merge); d) test; e) push. And in general you are right: git is usually unable to merge uncommitted changes (I asked [related question](https://stackoverflow.com/q/11223353/536172) few years ago, and apparently there is no progress in git with such feature, or I'm not aware of it). – AntonK Jun 23 '19 at 21:06
  • @AntonK So you are saying the `git` forces you to make a branch to make your own local changes as a standalone commit without any "pre merge" from any other place. Why this has to be always plus? Isn't it another `git` minus? – Andry Jun 24 '19 at 19:02
  • @Andy , with git you can commit locally without creating a branch , so it doesn't force you to create branches if you don't want to. The main point of my previous comment is about merging, which git can do automagically only after you commit your changes (locally). – AntonK Jun 26 '19 at 11:20
2

Keeping the answer short - In DVCS , since you have a local source control, if something get screwed up in the merge process (which will probably happen in large merges), you can always rollback to a previous local version which has the changes you've made before merging, and then try again.

So basically you can do merge without the fear that your local changes might get damaged during the process.

  • 2
    Doesn't really answer the question. What's different in a DVCS from SVN in your example isn't obvious. – jv42 May 31 '11 at 13:11
1

If you exclude "Merge-Refactored Hell" you will not get fair samples, because they just doesn't exist

Lazy Badger
  • 94,711
  • 9
  • 78
  • 110