How does git know which version of a line to keep?
I am working a on project which is released in a stable version once in a while. When we release a version we start developing the next version from the current HEAD.
The old version is however is still supported, put on it’s own branch and receives various minor fixes and features. When I apply a fix to an old supported version I (almost) always merge them into the current version as well.
- My application is called “libSSL”.
- I release libSSL version 2 and create a seperate branch with the code I released
- I continues develop libSSL version 3 from the libSSL version 2 codebase
- ….time passes…..
- I fix a critical security issue in libSSL version 2
- I merge the changes into my current code for the soon to be released libSSL version 3
I was just merging some changes from an old supported version into my latest branch when I came by this situation in git full res image here
It’s not a conflict but just some code clarification. I change in a variable which have been made at some point since the last release (probably a long time ago).
How does git know which variable name to use? I guess git could look up the timestamp for the commit when the change was made (and pick the most recent one) but that seems like a very expensive task and it doesn’t feel like that.
I normally don’t think twice about these non conflict changes but can I be sure that git will do the right thing? Is that a valid assumption, or should I pay more attention to them in order to avoid overwriting some new code with some old code?
I’m always merging the old branch into the new branch.
One Solution collect form web for “How does git know which version of a line to keep?”
Git is a content-addressable database, meaning every object is stored under the hash of its contents. Git also does 3-way merges. It finds the ‘merge-base’ (there’s even a command in git –
git help merge-base to read up on it) that finds the most recent ancestor that they have in common, i.e. the point that both forked off of at some point in the past.
Unlike 3-way merges in non-hashed systems, which need to diff files for comparison, git can look at the 3 hashes. Let’s say you’re merging feature into master. If the 3 hashes of a particular path to a file in the project are identical, it skips it – it hasn’t changed in either branch – this is super fast. If the hash has changed in master but not in feature, then it just uses the master version, because someone changed it on master, but no one cared to on feature, so the master version is the changed/important one. Vice-versa, if it changed in feature, but not in master, it just uses the feature version. This is also super fast. In fact, this is the majority case most of the time. Most files don’t change in larger projects, so a merge only ends up comparing some small set of files for which the hash has changed in both branches.
If the hash has changed in both branches from what it was at the merge-base of those two branches, then git falls back to merging the old-fashioned way, comparing things line-by-line. If one set of lines changed in one path, but not in the other (as compared to the merge-base copy), then it merges the changes from that branch. If you changed a variable name in both branches, then it would wrap it in conflict markers and tell you you need to resolve this manually, which is the only right way to do this. As Linus Torvalds said, you don’t want a machine trying to figure that out for you, and he’s right.