Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GIT :: Merging 2 branches overwrite the content in one branch with the other

I am experiencing a wild issue. I have my entire project in the master branch. Earlier, one guy was working on this project, but it was in SVN. He made some changes and I need to integrate those changes with mine. Both projects have the same folder structure, the only difference is the type of VCS used. I did the following

  • Downloaded his code and removed .svn folder
  • Created and switched to a new branch "code_to_integrate"(Points to my master branch)
  • Copied the downloaded code and replaced my project folder with it.(.git folder is kept as such)

At this stage, If I run git status command, I can see the changes(files are marked as modified) I need to integrate with my master branch. Then,

  • Committed those changes there.Let its commit id be c2
  • Checked out to my master branch.(commit id c1)
  • Merged it with "code_to_integrate" branch.

The result was that my code in the master branch overwritten with the code in the "code_to_integrate" branch. I lost my entire modifications. The HEAD is at c2 and I can see c1 as well. If I use

git reset --hard c1,

I will get back my changes. Right now, its like using the command

git merge -s theirs

I got the entire changes from the merging branch(code_to_integrate) and lost changes in merged branch(master). Whats happening?. This should be really straight forward right?. Any help will be appreciated. Thanks in advance

like image 555
Shibin Avatar asked Jun 30 '14 11:06

Shibin


People also ask

What happens when you merge two git branches?

Merging Branches. Once you've completed work on your branch, it is time to merge it into the main branch. Merging takes your branch changes and implements them into the main branch. Depending on the commit history, Git performs merges two ways: fast-forward and three-way merge.

Does merging affect both branches?

No, merging does only affect one branch.

What happens after merging a branch?

Let's go into merging in more detail. When you perform a merge, you effectively merge one branch into another—typically a feature branch or bug fix branch into a main branch such as master or develop. Not only will the code changes get merged in, but also all the commits that went into the feature branch.

How do I merge two branches in the same branch?

To do a merge (locally), git checkout the branch you want to merge INTO. Then type git merge <branch> where <branch> is the branch you want to merge FROM. Because the history of master and the history of make_function share common ancestors and don't have any divergence descendents, we get a "fast-forward" merge.


1 Answers

The problem is that you created the code_to_integrate branch on top of you master branch. So things looked like this:

... -> oldercommit -> oldcommit -> c1 (master, code_to_integrate)

When you then committed the other guy's code to this branch you get a linear history:

... -> oldercommit -> oldcommit -> c1 (master) -> c2 (code_to_integrate)

When you now merged code_to_integrate into master git detected that c2 is just newer than c1 and did a so called fast forward merge, which basically means only changing the commit that master points to to c2. Imagine code_to_integrate was just a quick branch you yourself made to do some work on, e.g. fix a bug. Once you are done you would have the exact same history and a fast forward merge would be precisely what you want.

In order to fix you problem you need to tell git which of you old commits is the newest common ancestor of your and the other guy's work. Basically you need to tell git at which point in time the other guy branched off your master. You so that by checking which is newest commit that both you and the other guy have in your history and then starting the code_to_integrate branch there. Assuming that the other guy branched off at oldercommit, you would do a git checkout oldercommit followed by a git checkout -b code_to_integrate and should get something like this.

... -> oldercommit (code_to_integrate) -> oldcommit -> c1 (master)

Once you commit the other guy's version you get:

             -> c2 (code_to_integrate)
            /
... -> oldercommit -> oldcommit -> c1 (master)

When you now merge code_to_integrate into master, git will see that there is a divergent history and do a three-way merge (where oldercommit is the mergebase), prompting you to resolve any conflicts that might arise, etc. This is what you want!

So in summary you simply started your code_to_integrate branch from the wrong commit. There is no way git or any other version control system can do a merge without knowing what the mergebase is.

EDIT: If you did not share any changes with the other guy since you put the code into git, then your mergebase is the oldest commit in your history. The following should do what you want:

git checkout $(git rev-list --all | tail -n 1)
git checkout -b code_to_integrate
[ ... put the other guys code into your working directory and commit it ... ]
git checkout master
git merge code_to_integrate

The first command checks out the oldest commit in your history, which is the last one that you and the SVN guy have in common. The 2nd command creates the code_to_integrate branch at your oldest commit and switches to it. Then you throw the other guys code into your working directory and commit it to the code_to_integrate branch. Finally you switch back to your master branch and merge the other branch in.

like image 65
Robert Rüger Avatar answered Oct 31 '22 03:10

Robert Rüger