I get stumped when git diff other_branch
shows differences and git merge other_branch
does nothing. What's the right way to incorporate that "missing" code into my_branch
?
This SO answer diagramed a situation similar to mine.
o---A---B---C-------G my_branch
\ \ /
--*D*---E---F other_branch
Surprisingly changes in D aren't automatically merged into my_branch
when I do
git checkout my_branch
git merge other_branch
to bring in F to G
Of course I can manually create a patch and apply it to my_branch
, like this:
git diff other_branch my_branch > patchfile
git checkout my_branch
patch -p1 < patchfile
But I want to do this right, without mucking up the git log. With the patch approach, git will record the changes in D and my latest patch as happening independently of each other (code churn). I want to simplify the git log
and make sure others don't have unintended things happen (quietly and insidiously) when they do a git merge my_branch
.
You seem to have two issues here at the same time.
Assuming a history like the one you described:
my_branch
v
----A---B---C-------G
\ \ /
--*D*---E---F
^
other_branch
Why the diff is not empty:
This situation is produced by the commands you mentioned, i.e. being on my_branch
and then doing git merge other_branch
. This action produced a merge commit G
and moved the current branch (my_branch
) forward, but left other_branch
where it was. This is how merges always work! Naturally, there will still be a difference between my_branch
(G
) and other_branch
(F
) at this point -- they point to different commits after all.
If you want the two branches to be identical, you can move up other_branch
in the following ways:
git checkout other_branch; git merge my_branch
-- this is a fast-forward merge since G
is a descendant of F
other_branch
!] git branch -D other_branch; git branch other_branch my_branch
-- this will remove other_branch
and then re-create it in the same location where my_branch
currently isgit checkout other_branch; git reset --hard my_branch
-- this will move other_branch
to point exactly where my_branch
is currently pointingAfter doing one of these steps, both my_branch
and other_branch
will be pointing to G
.
Why the changes of commit D
are not in my_branch
(G
)
Git merges histories, not changes. This usually means that Git will take the two sides of a merge (and, if available, their youngest common ancestor commit, aka the merge-base) and try to combine them. Since Git commits are snapshots, not changesets/deltas/diffs, this no information of other commits or changes is used in the actual merge.
Using the merge-base, Git does a so-called three-way merge, using the common ancestor to try and smartly resolve the changes on both sides. If it can't it will interrupt the merge and require the user to resolve the conflicts.
What probably happened in your history is that either commit E
or F
reverted (or overrode) the changes of D
-- this might have happened during the merge which produced E
or actual (manual) changes in F
.
As you yourself mentioned in a comment, you often switch between commits and make edits. You will thereby be floating changes a lot (Git carries uncommitted changes over during checkouts), which might very well make it difficult to tell where changes should go and where they actually do go. Try to avoid this by either committing any changes before changing branches or using git stash
to buffer them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With