5

我有一个父分支 A 和一个子分支 B。在分支 B 中,我有两个单独的提交。我像这样将A中的分支B与壁球合并

git merge --squash B 

当我将分支 A 与分支 B 进行比较时:

git log A..B

它将来自分支 B 的两个提交显示为未合并。我如何将它与父分支 A 的压缩提交进行比较?这样它就可以在两个分支之间的响应没有差异

谢谢

4

1 回答 1

6

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.)

于 2014-09-24T07:00:15.500 回答