I was working in a feature branch called BR1 that is branched off master.
At this time master and my branch has the file a.js
with content:
1: console.log(`Hello Duck`);
About 20 days after BR1 was created, the master was reverted to a past commit. Now the content of a.js
in master was changed back to:
1: console.log(`Hello Dog`);
During this time I changed a.js
in my branch adding some more code:
1: console.log(`Hello Duck`); // this line was not changed
2: if (foo === bar) return; // added this line.
How can I merge my BR1 branch into master, avoiding replacing content a.js
from my branch into master. I want to preserve the master content on the lines that i didn't change/add. I want something like this:
1: console.log(`Hello Dog`);
2: if (foo === bar) return; // add this line.
CodePudding user response:
In Git, the word revert has a different meaning than the word reset, and they are not interchangeable. You revert a commit by creating a new commit which does the opposite of the commit you are reverting, effectively undoing the change. When you reset a branch, you change what commit the branch is pointing to, and if you move it backwards to an older commit on the branch, then all commits after that are effectively deleted from that branch.
Given these definitions, it doesn't make sense that:
master was reverted to a past commit.
I'm assuming you meant to say:
master was reset to a past commit.
Why does this matter?
If the commit that changed the line in question had been reverted on master
, then when you merged your branch into master
you would have had a conflict which you could have resolved by picking the exact result you wanted (taking the older first line and your newer second line). But since master
was reset, your branch appears to Git to be all newer changes, so Git will select all of your changes without prompting for conflict resolution.
So what should you do?
There are multiple things you can do, two of which are:
After further thought, do not choose this option.
Simply change the first line of your file to look like how it does on the currentThe problem with this option is that you will bring back commits that were deleted frommaster
branch, and commit that on your branch with a title message like "Update due to branch reset" and perhaps more information in the commit message details. Now when you merge in your branch you won't affect the lines that were un-done due to the reset.master
with the reset, which presumably were deleted purposefully.Do this: Rebuild your branch as if it came off of what the current
master
looks like. There are multiple ways to do this, but conceptually you create a new branch off of the currentmaster
and then cherry-pick each of your commits onto that branch. You'll get a conflict on the line in question for the first change that you'll need to resolve. You could also do a "fancy" rebase of your branch with something similar to:git rebase --onto current-master old-master
With rebase you'll also need to resolve the conflict in the first line.
Side Note: This is one of the reasons resetting a shared branch such as master
is frowned upon, since it can mess up all branches that are based off of it, which is exactly what happened in your case.
CodePudding user response:
Just do it. You'll have to tell Git the right result for that pair, it'll (correctly) notice the changes to abutting lines and ask for a human judgement call about whether and how they interact. This can be surprising in the "they don't" cases like this, but the point is, often enough they do, and Git assuming they don't would be a Very Bad Call.
Get good with the tools, trivial cases like this take like two seconds to resolve.
git init testmerge; cd $_
echo Hello Duck >t1; git add .; git commit -m duck
git checkout -b br1
echo new line >>t1; git commit -am newline
git checkout master;
echo Hello Dog >t1; git commit -am dog
git merge br1
and Git reports a conflict, abutting lines changed. It doesn't matter what order you make the conflicting commits, what matters is only that the two tips have changes to overlapping or abutting lines.