Reputation: 943
I am confused with git merge.
Suppose i have feature
branch taken from master
and they have divergedliek this
and they merged like this
Now i want to know that what will be the diagram after this command
git checkout master
git merge new-feature
What will be the diagram after this command
git checkout master
git merge new-feature
provided after that i dont close feature branch after that and just do one more commit after that on feature branch
Upvotes: 3
Views: 4343
Reputation: 490078
The answer is: nothing happens to the feature
branch as a result of the merge. The new merge commit is added on the current branch (which is master
when the merge is done). No existing commit is affected, as no existing commit can ever be changed at all.
As an aside, the arrows between commits really should point the other way. New commits point back to older commits; older commits can never be modified, not the least little bit, so there's no way to "add an arrow" to an older commit. You can only make a new commit, which then has one or more back-pointing arrows, to one or more older commits. (One arrow per pointed-to-commit, that is. You can even make a new commit with no back-pointing arrows: this is a new "root commit". That's a bit more of an advanced thing, though, and not all that common in repositories.)
Although the ASCII art version is not as pretty, these are the same before and after diagrams:
o-o <-- feature
/
o--o--o--o <-- master
[becomes:]
o-o <-- feature
/ \
o--o--o--o--o <-- master
If you then check out feature
and add another commit to feature
after this, it becomes:
o-o--o <-- feature
/ \
o--o--o--o--o <-- master
Edit: let's re-draw that last picture (same picture, we'll just put a name m1
, for "merge #1", in place of one of the o
s representing a commit):
o-o--o <-- feature
/ \
o--o--o--o--m1 <-- master
Now suppose you continue developing away on feature
, adding two more commits:
o-o--o--o-o <-- feature
/ \
o--o--o--o--m1 <-- master
and then decide to merge feature
into master
again. To do this, git will need to make a new merge commit, m2
:
o-o--o--o-o <-- feature
/ \ \
o--o--o--o--m1------m2 <-- master
The merge base for the new merge is derived by looking at the old merge, so that git can tell that only the three latest feature
commits need to be brought in.
This is why, if you decide that something from feature
has broken master
and you "undo" it before adding merge m2
, you need to manually "redo" it if needed. That is, suppose that after making merge m1
but before adding the three new commits on feature
, you find that master
is broken and you add a commit f
("fix by removing a piece of feature"):
o-o <-- feature
/ \
o--o--o--o--m1--f <-- master
Now you go ahead and work in feature
as before, adding the three commits:
o-o------o-o-o <-- feature
/ \
o--o--o--o--m1--f <-- master
Now when you go to git merge feature
into master
, git will again find the base, and know just to take the changes from the three newest commits and add them to f
:
o-o------o-o-o <-- feature
/ \ \
o--o--o--o--m1--f------m2 <-- master
But commit f
deliberately disabled part of the new features. You may have to manually fix up the merge (either before making commit m2
, or in a separate commit after m2
—how you want to do it is up to you) that "undoes" the fix in f
, re-enabling the full feature.
Regardless of whether and when feature
is to be merged back into master
again later, you can choose whether or not to merge master
into feature
. Let's assume for instance that there's something especially G
ood in master
that should be brought into feature
:
o-o <-- feature
/ \
o--o--o--G--m1 <-- master
Here you can just:
git checkout feature && git merge --no-ff master
to bring the changes in G
and m1
into feature
. Of course the changes in m1
are already there, but git can figure this out itself, so it will really only bring in the good stuff from G
:
o-o----m2 <-- feature
/ \ /
o--o--o--G--m1 <-- master
The --no-ff
is only needed if you want an explicit merge commit, which is useful for making the development line of "feature" stand out. If you leave out --no-ff
, git will observe that bringing m1
into feature
results in, well, m1
, and will just move the branch label in a "fast forward" operation:
o-o
/ \
o--o--o--G--m1 <-- feature, master
If you're "on branch feature" (git checkout feature
) and make a new commit, that will leave the label master
pointing at m1
, and feature
pointing at your "new newest" commit:
o-o
/ \
o--o--o--G--m1 <-- master
\
o <-- feature
I put feature
down below to emphasize that it's not obvious that the "top" o-o
line was once on feature
.
Note that this graph is the same as this alternative drawing that looks a bit like a snail:
o-o o <-- feature
/ \ /
o--o--o--G--m1 <-- master
which kind of hints that the o-o
might have been on feature; but is very different from this drawing, which includes m2
:
o-o----m2--o <-- feature
/ \ /
o--o--o--G--m1 <-- master
and which makes it very clear that feature
has an unbroken lineage going back to the earlier top o-o
. This is basically what "other direction merging with --no-ff
" is for.
(Do you want it? Well, that depends on you, really. Graphs like the "snail" one are very common, and you get used to them and knowing which branch-label was on some commit sequence some time in the past is often not very useful. But sometimes it is useful, and then you want the graphs that look more like tents and geometric things, rather than snails. :-) )
Upvotes: 14