I am working in branch A and have the following code in some file
some.property=abc
new.property=def
#some.commented.props=
and in the master branch, the same file contains the following code
some.property=abc
#some.commented.props=
Now after git pull origin master
this file is auto merged and here is the final code
some.property=abc
#some.commented.props=
My question is why the codes from branch A are not added to the file? Seems like it kept the code as it is in the master branch.
I added other codes as well but they are properly added, or show conflict where necessary.
CodePudding user response:
What's happened here is virtually certain to be what Jay suspects in a comment. Remember that Git's git merge
command is about combining work. It does not mean "override all their files from my files". Instead, it means:
- figure out what they changed;
- figure out what I changed;
- combine the two sets of changes and apply those changes to our common starting point.
It looks like what you changed was some other files, leaving:
some.property=abc
new.property=def
#some.commented.props=
in some file alone.
What they changed is various files, plus changing that one file to read:
some.property=abc
#some.commented.props=
That is, they deleted the new.property=def
line.
So Git combines your changes—"do nothing here"—with theirs, "delete this bad line", and the result is that you now have the bad line deleted too.
If the line wasn't actually bad—for instance, perhaps new.property=def
was intentional, but just not used yet until you started using it—then what's going on here is that his change is the bad thing and your lack-of-change is the good thing, and you must adjust the merge result because Git is not able to assess the value of any particular change. Git merely combines your changes (none) with his (delete the line), even if his change is a bad thing.
You have three ways to fix the problem:
You can make a new commit on his branch that puts the line back, so that he has not deleted the line. Now he has no "delete the line" change, so that Git won't merge your changes and "his" (now his your) changes by deleting the line, since the line is no longer deleted.
You can use
git merge --no-commit
to have Git compute the merge result and set it all up, but not actually commit it. Then you can fix the one file before committing, and commit this result. People refer to this as an evil merge, though in this case there's no actual "evil" involved. Be careful with this kind of merge because someone trying to repeat your work later won't necessarily know that you did this, and may get it wrong. Or:You can go ahead and let
git merge
delete the line, then make a separate commit just after the merge that puts the line back. Use a commit message that explains what happened and why this is necessary. A sample commit message would be:restore new.property=def In the preceding merge commit, the property definition for "new.property" got deleted because the team working on branch xyzzy noticed that this property was not used and thought that it should be deleted. However, this property was added back in commit <insert hash ID> with the intention of using it in the future. That future has arrived, so the setting needs to be restored: the deletion was an error. (When bisecting, skip the merge commit as it's known to be bad and to be corrected by this fixup.)
There's no really strong reason to prefer any one of these three, but in general my own preference is to fix their branch first if the resulting commit does not break anything. Make the commit message similar to the above, or consider folding that commit in as a fixup so that they never end up deleting the line at all.
To avoid similar future errors, either defer adding new properties until they're actually about to be used, or be sure to update documentation (perhaps comments in the configuration files that hold the properties) to mark these as "for future use, do not delete" or similar.