Keep event history after git merge

When I work on two different functions (on two different branches created by the wizard), it is rather annoying that I will not have a commit history when I start the merge.

I will explain better. When I finish work on Branch-A, I combine it into a master. And that is fine, if I git log , I see all the commits that I made in Branch-A.

Instead , when I finish working with Branch-B and I try to merge it into master (after Branch-A has already been merged), I have to specify a commit message to merge (while for the first branch I was asked nothing ) And after merging with the master, if I type git log , I cannot see Branch-B commits in the history of my main branch

Say I have

 **Branch A** commit 09b2unfas9d781n2e Add more stuff commit 8uj8masd89jas898a Add stuff **Branch B** commit 09b2unfas9d781n2e Add feature setting commit 8uj8masd89jas898a Add feature 

I end up being

 **Master** commit 6hf6h8hd871udjkdn Merge: 09b2un 34osd6 Merge branch 'Branch-B' into master commit 09b2unfas9d781n2e Add more stuff commit 8uj8masd89jas898a Add stuff commit 34osd62dhc91123j8 I'm a previous commit from 'master'. The last one before branching... 

while I would like to get something like:

 **Master** commit 09b2unfas9d781n2e Add feature setting commit 8uj8masd89jas898a Add feature commit 09b2unfas9d781n2e Add more stuff commit 8uj8masd89jas898a Add stuff commit 34osd62dhc91123j8 I'm a previous commit from 'master'. The last one before branching... 

... that more accurately reflects the history of commits executed.

I do not understand why I can save a story from only one of the two branches.

How can I keep everything clear without these commits that hide / skip the real history of merged commits?

+11
git git-branch merge github
Feb 09 '15 at 9:57
source share
2 answers

The first merger seems to have been quick, and the second is a tripartite merger.

Explanation

Git has two versions of merging: accelerated and tripartite. (There are other versions, but that is not what happened here.) The default behavior is to perform a quick merge whenever possible, and otherwise do a three-way merge.

Fast merging (you can force this behavior with the --ff-only option, which will cause the merge to fail when fast-forward is not possible) can occur when a merge that merges has the current position of a branch in its history. For example:

 A - B - C - D <-master \ E - F - G <- branch-a 

Excecuting git merge (with default settings) will result in

 A - B - C - D - E - F - G <- branch-a <-master 

You will also not be able to edit the merge commit because it does not exist. However, as soon as this happens, your other branch diverges from the master (not just forward):

 A - B - C - D - E - F - G <-master \ E1 - E2 <- branch-b 

Therefore, Git cannot just move the master pointer from G to E2 , because it will save you from changes made to F and G Instead, a three-way merge occurs, which creates a commit that has two parents and also has a commit message. Now the wizard can be moved to this commit. (Note that in this situation, master and branch-b do NOT point to the same commit.

 A - B - C - D - E - F - G - H <-master \ / E1 - E2 <- branch-b 

If you want to have a linear history, you need to use rebase, but be warned that if anyone else sees that your branch is doing this, this can lead to problems that are beyond the scope of this answer. Using rebase will include two steps, a reboot, and a subsequent merge. So, instead of merging, you first do the following: branch-b , git rebase master . This creates new commits that are copies of old commits, i.e. The same set of changes, information about the author and the message, but new information about the participants and the parent story. (I will call the commits E1 'and E2' in the illustration to indicate that they are just copies.) Old commits will exist until they are garbage collected, but not accessible unless you look at the reflog. )

 A - B - C - D - E - F - G <-master \ \ E1 - E2 \ E1' - E2' <- branch-b 

Running git checkout master; git merge --ff-only branch-b git checkout master; git merge --ff-only branch-b will now speed up the forwarding of changes to master, thereby giving you a linear history.

 A - B - C - D - E - F - G - E1' -E2' <-master <- branch-b 
+11
Feb 09 '15 at 10:24
source share

Use rebase instead of merge . From the textbook:

If you look at the log of the reinstalled branch, it looks like a linear story: it seems that all the work happened in sequence, even when it originally happened in parallel.

I assume that changes from your Branch-B cannot be merged using fast forward , merge to master . In such cases, a three-way merger is performed:

Instead of just moving the pointer to the branch forward, Git creates a new snapshot that comes from this three-way merge and automatically creates a new commit that points to it. This is called a merge commit, and is special in that it has more than one parent.

I will always reset my commits before sending them to master in order to keep a linear history.

0
Feb 09 '15 at 10:07
source share



All Articles