Will doing this particular merge delete the common commits instead of re-applying them?

0

Issue

I’ve been reading an article over here: https://medium.com/anitab-org-open-source/how-i-managed-to-not-mess-up-my-git-history-thanks-to-git-pull-rebase-fed452c661f0

Based on my understanding she’s got the following structure (excuse me for the rough sketch):

git example commits

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?

Solution

Let’s address your questions individually.

AFAIK, if task2 is merged to master, it’ll take that entire path that connects it until master and merge all that to master.

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 with master. If we merge task1 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 merging task1 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 after task2, wouldn’t it cancel out (delete) the register folder/file that got merged by task2 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.

Answered By – Enrico Campidoglio

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave A Reply

Your email address will not be published.

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More