Dev wants to update featureBranch with updated changes from origin/master branch, and then push their local changes to origin/featureBranch
git checkout featureBranch
git add .
git commit -n -m "message"
git checkout master
git fetch
git checkout featureBranch
git merge master --no-verify
git push origin featureBranch
I see a completely blank commit (merging with dev), with 0 additions and 0 removals. Why?
CodePudding user response:
There is not enough information in the question to say exactly why you got a merge commit, but there are several possibilities:
A merge commit is necessary. This occurs if the two branch-tip commits are both ahead of the shared (common) merge base commit. That can happen even if there are no changes involved in making the merge.
A merge commit was forced. That happens with GitHub's MERGE button always, and with command-line Git, happens if you specify the
--no-ff
option. You can include this option in your configuration, in which case we would not see it on the command line.A fast-forward was possible but the argument to
git merge
was that of a tag and the tag:is not stored in its natural place in the
refs/tags/
hierarchy(as described in the
git merge
documentation, under the--ff
,--no-ff
,--ff-only
options).
(in decreasing order of probability). The last would require that the name master
be resolved to a tag object, which is pretty unlikely but not technically impossible. The middle would occur if you configured merge.ff
to false
. The first is the most likely as it is quite common.
I see a completely blank commit (merging with dev), with 0 additions and 0 removals. Why?
No commit is ever blank (nor empty, despite the git commit --allow-empty
option spelling). A commit always contains:
- a full snapshot of every file (with the usual compression and de-duplication), plus
- metadata.
A merge commit contains metadata listing two or more parent hash IDs: that's what makes it a merge commit in the first place. An ordinary (non-merge) commit has one parent, and at least one commit in every non-empty repository is the very first commit and therefore has no parent, making it a (usually the) root commit. Every commit also has a full snapshot of every file: merge commits are no different here.
Suppose we have the following series of commits, and two branch names br1
and br2
selecting their tip commits:
I--J <-- br1
/
...--G--H
\
K--L <-- br2
Running:
git checkout br1 && git merge br2
will, if all goes well, produce the new merge commit M
on branch br1
and leave us with:
I--J
/ \
...--G--H M <-- br1 (HEAD)
\ /
K--L <-- br2
The snapshot for commit M
is that made by:
- finding the differences (various files changes) from
H
toJ
; - finding the differences from
H
toL
as well; - combining (merging) those differences; and
- applying the combined differences to the snapshot from commit
H
.
This keeps the H
-to-J
changes and adds the H
-to-L
changes, if you like to view it that way, or it keeps the H
-to-L
changes and adds the H
-to-J
changes: sums are (at least for non-conflict cases) commutative, like integer arithmetic: 3 7 = 10, but 7 3 = 10 too.
If whoever made the br2
changes copied exactly the br1
changes, the "sum" that Git makes here will be to keep just one copy of the changes. So the snapshot in M
will match both of those in J
and L
(which themselves both match). That would show as no additions and no removals.
If whoever made one of the two branches made a change, then reverted it, so that the snapshot in one of J
or L
matched the snapshot in H
, that "side" of the merge would have no contribution, and the snapshot in M
would match the other commit. If the "side" that had a net-zero contribution was br2
, that too would show as no additions and no removals.
Without more (e.g., the output from git log --graph
, perhaps with --oneline
, and/or the results of git merge-base
from before the merge plus the appropriate git diff
commands to see what changes Git is merging, and/or the result of git config --get merge.ff
) we can't say which of these might have triggered the "empty" merge (to misuse the word "empty" the way Git does).