I've been reading an article over here:
She states the following problem:
What if X approved task 2 and merged it first then review task1 and merged it after? Remember that task 1 has no additional codes that task 2 has since it was the preceding task. To make more sense, think of it with task 2 as the Register functionality and task 1 as the basic setup. Basic setup branch won’t have the Register files since I didn’t write that functionality on task 1. If this task 1 branch is to be merged after task 2, wouldn’t it cancell out (delete) the register folder/file that got merged by task 2 from the first merge? How can we prevent this?
This is the sentence that boggles my mind:
"If this task 1 branch is to be merged after task 2, wouldn’t it cancell out (delete) the register folder/file that got merged by task 2 from the first merge?"
AFAIK, if task2
is merged to master, it'll take that entire path that connects it uptil master
and merges all that to master
.
task1
would only have 2 commits that aren't merged with master (consider those slashes to be commit ids). If we merge task1
afterward, it shouldn't have any problems whatsoever.
Or, if task#1
didn't have any extra commits then merging task#1
wouldn't lead to any problems, isn't it?
It's not like commits will be "canceled out" or "deleted" if we merge task1
. Correct?
CodePudding user response:
Let's address your questions individually.
AFAIK, if
task2
is merged tomaster
, it'll take that entire path that connects it untilmaster
and merge all that tomaster
.
Correct. The resulting history would look like this:
o---o--------------M (master)
\ /
o---o---o---o (task2)
\
o---o (task1)
task1
would only have 2 commits that aren't merged withmaster
. If we mergetask1
afterwards, it shouldn't have any problems whatsoever.
Also correct. There might be some merge conflicts depending on what changed in task1
, but nothing out of the ordinary. The resulting history would look like this:
o---o--------------M---N (master)
\ / /
o---o---o---o / (task2)
\ /
o---o (task1)
Or, if
task1
didn't have any extra commits then mergingtask1
wouldn't lead to any problems, wouldn't it?
Nope. Git would literally tell you Already up-to-date.
and call it quits.
It's not like commits will be "canceled out" or "deleted" if we merge
task1
. Correct?
You're correct, commits are never deleted by a merge. Files, however, might. It depends on whether they were actively removed from the index by one of the commits that are being merged.
See, the fundamental problem with the statement you quoted from the article is this:
If this
task1
branch is to be merged aftertask2
, wouldn’t it cancel out (delete) the register folder/file that got merged bytask2
from the first merge? How can we prevent this?
When you do a merge, Git combines the trees associated with the commits you're merging compared to their first common ancestor (known as the merge base). If a file that existed in the common ancestor was deleted in one of the commits on one side of the merge, then yes, that file would be deleted in the resulting merge.
To go back to our example:
o---o--------------M-----N (master)
\ / /
o---o---o---o / (task2)
^ \ /
foo.txt o---o (task1)
^
deletes foo.txt
If foo.txt
existed in the common parent between task2
and task1
, and task1
deleted it, then foo.txt
would be removed in the merge commit N
. It's worth noting that if task2
modified foo.txt
after task1
's fork point, then you would get a merge conflict.
Now, if task2
created foo.txt
, merging task1
wouldn't delete it in master
simply because foo.txt
doesn't exist in task1
:
o---o--------------M--------N (master)
\ / /
o---o---o---o / (task2)
\ ^ /
\ creates foo.txt
\ /
o---o (task1)
In this case, foo.txt
would exist in the merge commit N
.
If you're curious to see what the resulting tree would be like if you merged two branches, you can use the merge-tree
command. For example:
git merge-tree $(git merge-base master task2) master task2
This would print out the paths of the files included in the tree that results from merging master
and task2
.