Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do the commit ids remain same after a merge?

My team uses git and Bitbucket for version control.

I had previously created a Pull Request from one of the branches of my repository to one of the branches of the team's main repository.

This pull request was accepted and my branch was merged in.

Yesterday I added some changes to the same branch in my repository. When I tried to create a pull request to the same branch on team's repository, I was notified of some merge conflicts.

I viewed the commit log of the team's branch and realized that although the commit message, author(me) & date were same, the commit id was different in the remote branch.

What could be the problem here?

I was under the impression that even after merge commit ids are preserved.

Could something else be causing this?

P.S. I have read that cherry-pick can change commit ids. Any thoughts?

like image 902
kmdhrm Avatar asked Jul 28 '14 10:07

kmdhrm


People also ask

What happens to commits after merge?

This sort of commit is called a merge commit. And that's not all. After the merge, the working tree and the index and the HEAD (the new merge commit) are all synchronized. In other words, Git does not merely make a new commit; it also changes the state of your working tree (and the index).

Are commit IDs unique?

Commit IDs are unique SHA-1 hashes that are created whenever a new commit is recorded.

Does git merge Keep commits?

The old commits will exist until they are garbage collected, but will not be reachable unless you look at the reflog.) Executing git checkout master; git merge --ff-only branch-b will now fast-forward your changes into master, thereby giving you a linear history.

Does merge also commit?

Git merging combines sequences of commits into one unified history of commits. There are two main ways Git will merge: Fast Forward and Three way. Git can automatically merge commits unless there are changes that conflict in both commit sequences.


1 Answers

Merges neither preserve, nor fail to preserve, commit-IDs. Merges make new commits (assuming you do them in such a way as to avoid a "fast forward" operation, anyway).

That is, given a sequence of individual commits that I will label with single letters:

A - B - C
      \
        D

commit C (which might perhaps really be ID 6da748a...) has commit B its parent, and commit D (perhaps actually 740c281...) also has commit B as its parent. To merge these two commits, git must create a new commit with two parents:

A - B - C - M
      \   /
        D

This new commit M has a different ID from every other commit, but commit D is completely unchanged and therefore still has its same ID (740c281...).

Many people try to avoid making this kind of relatively-trivial merge. Instead of taking their work (commit C) and your work (commit D) and making a new merge commit, they make a copy of your commit message—including author and date—and make the same changes to C that you made to B. This operation is indeed called "cherry picking" (and also "rebasing"), but it makes a new, different commit, which we might call D', with a new, different commit-ID:

A - B - C - D'

The most obvious difference between your original D and this new D' is that D' has commit C as its parent, rather than commit B. (It also has different tree contents, in normal cases, since your B-to-D changes were applied to files as seen in version C, which are likely different in some places from those in B.)

Commit D' is not a merge commit, however. (A merge commit is any commit with at least two parent commits. Use git log --graph or gitk or some other graphical viewer to see the commit graph more directly.)

If your work is rebased (or cherry-picked) into an upstream, and you fetch and then attempt to merge the upstream, git will sometimes, but not always, be able to detect the duplication and clean up automatically. When it cannot auto-detect the duplication, you will almost always get various merge conflicts: git sees you trying to change some code (in your commit D in the above example), and them trying to change the same code, but in a slightly different way (in their commit D' in the above). For this reason, it's generally not considered very polite to rebase someone else's code: instead, upstreams tend to ask you to rebase your code yourself (while it's still private to you) and then they can include it as a "fast forward" (merge-free) addition to their repository.

(This way you can also make any changes required by the rebase operation yourself. For instance, if you fixed a bug in your version D that they also fixed in their C, but you and they took different approaches, you can resolve this conflict—possibly more easily than they can since you know what you did and why you did it that way, and whether your new feature depends on your version of the fix.)

like image 78
torek Avatar answered Oct 31 '22 21:10

torek