Compare branches after git merge with --squash
Asked Answered
S

2

6

I have a parent branch A with a child branch B. In branch B i have two separate commits. I merged branch B in A with squash like this

git merge --squash B 

When i compare branch A with branch B:

git log A..B

It shows the both the commits from branch B as un-merged. How can i compare it with squashed commit of parent branch A ? so that it can get no difference in response between both the branches

Thanks

Stephan answered 24/9, 2014 at 6:39 Comment(0)
S
8

Quoting the git merge documentation, --squash means:

Produce the working tree and index state as if a real merge happened (except for the merge information), but do not actually make a commit or move the HEAD, nor record $GIT_DIR/MERGE_HEAD to cause the next git commit command to create a merge commit. This allows you to create a single commit on top of the current branch whose effect is the same as merging another branch (or more in case of an octopus).

In other words, after you git commit the result, you just have an ordinary commit, not a merge commit. The tree associated with this ordinary commit—what you get in the work-directory if you check it out—matches the tree you would have gotten by doing a merge, but no actual merge is recorded.

Given the setup you described, you had this before running git merge --squash B:

...- o         <-- A
      \
       o - o   <-- B

as your commit graph. After git checkout A; git merge --squash B; git commit -m squash-B you now have:

...- o ----- *   <-- HEAD=A
      \
       o - o     <-- B

Note that there is no commit-graph connection between the latest commit * and either of the two commits that are exclusively on branch B. The tree for commit * is the same as the one you would have gotten by doing a regular merge, but the commit graph is different: a real merge would have looked like this:

...- o ----- *
      \     /
       o - o

(I left out the branch labels here to emphasize that this is not what you actually have).


The dot-dot notation A..B asks for "commits reachable from B, minus commits reachable from A". The graph looks like this (same as a few above, just repeated here for clarity):

...- o ----- *   <-- HEAD=A
      \
       o - o     <-- B

The two o commits along the lower section are reachable from B, along with the upper o and any earlier commits; but the upper o and any earlier commits are reachable from A by starting at the commit marked * and working backwards, so these are excluded. That leaves just the two o commits: the one at the tip of branch B, and the one before it.

Note that if you had done a real merge, A..B would be empty as all commits reachable from the tip of branch B would also be reachable from the tip of branch A. (And, by contrast, B..A would be just commit * since that commit would be reachable from A but not from B; but this is true with the no-actual-merge squash-only history as well.)

Strutting answered 24/9, 2014 at 7:0 Comment(2)
Is there any way to get only squashed commits ?Stephan
No. The key point here is that git merge --squash does not make a merge commit (it does not make any commit at all!) so there is nothing distinguishing your subsequent manual commit from any other commit you made. (You could make sure that you give such commits a special commit message string, and then search for your own special string, but that requires that you adhere to your self-defined protocol well in advance of your eventual desire to find such commits.)Strutting
C
0

You can't use git for that. If you need to compare the files you could maybe use some sort of file comparing tool.

When you perform a squash merge, a merge commit isn’t created; instead, the changes from one side are applied as a regular commit to the other side. This means that the merge base for these branches won’t have changed, and so when Git goes to perform its next merge, it considers all of the changes that it considered the last time plus the new changes. That means any conflicts may need to be re-resolved. Similarly, anything using the ... notation in git diff, git log, or a GUI will result in showing all of the changes since the original merge base.

Squash merging condenses the history of changes in your default branch (...) When squash merging, it's a good practice to delete the source branch. Deleting the source branch prevents confusion as the topic branch itself doesn't have a commit merging it into the default branch.

Sources:

Merge strategies and squash merge

What kinds of problems can occur when merging long-lived branches with squash merges?

Calcific answered 26/8, 2022 at 17:23 Comment(2)
A bunch of quotes and links is not much of an answerTormentil
@Tormentil yes it isCalcific

© 2022 - 2024 — McMap. All rights reserved.