I am trying to merge two branches
alpha_critical
gamme_mine
gamme_mine is mine and would need everything from alpha_critical
When i do
git difftool f78606e3c60 94482fe3610
it shows all of the files which are different in these two commits from different branches. However
1 when i save and close the file with difftool the changes get lost
2 I thought about using mergetool instead but when i do
git mergetool f78606e3c60 94482fe3610
it says
No files need merging
Ultimately I just want to compare two specific files from these two branches and save the changes on my branch like this
git mergetool f78606e3c60:./test_basic.py 94482fe3610:./test_basic.py
TL;DR:
git mergetoolcannot be run until after you rungit mergeand it stops in the middle with a merge conflict.Long
A merge operation involves three, not two, commits, and in general is substantially more complicated than a diff operation, which only involves two commits. A diff is, in effect, stateless: it takes what you have and compares things, and shows you the result of the comparison. You can therefore run
git difforgit difftoolat any time. As you saw, changes you make ingit difftooldon't normally affect the files: the diff is operating on a copy of each file, and the copy goes away when the operation is done.Merging is not stateless. Merging has a distinctive starting phase, in which you and Git cooperate to find the three commits of interest. This is followed by an extensive middle part, in which Git computes two diffs—one from the merge base to your current commit, and one from the merge base to the other commit—and attempts to combine the two diffs. Git can sometimes complete this phase on its own. Sometimes, it cannot, and must stop and get help. Even if Git can do this on its own, you can instruct Git to stop, as if it was unable to complete the merge on its own.
In any case, once the second phase is done, the merge enters its third and final phase. This involves making a new commit. The new commit is almost exactly like any ordinary (non-merge) commit, with one key difference: the new commit has two parents instead of the usual single parent.
It is, I think, helpful to view an illustration of how merge works. Imagine each commit being identified by some hash ID (which is actually the case), with each commit linking back to a previous commit (which is also actually the case). Your two branches both descend from some common commit, like this:
Each round
orepresents some commit, which holds some snapshot of every file. Newer commits appear towards the right. The common shared commit is the the one labeledB(for Base). Since this commit is on both branches, and is just a single commit, every file here is the same in both branches. So if we compare commitBto commitT(--theirs), whatever is different—whatever diff would show—must be changes that they made. If we compare commitBto commitH(--oursorHEAD), whatever is different must be changes that you made.Git's job will be to combine these differences. To the extent that Git can do this on its own, it will apply the combined differences to the snapshot from commit
B. Where it cannot, it will record a merge conflict.The
git mergetoolcommand does not start or perform a merge. Instead, it picks up from the point where Git gave up with a merge conflict.Let's say that some file named
main.pyappears in commitsB(base),H(yours), andT(theirs), but that it is changed in both yours and theirs, and one of the changes was to change the usage message. Unfortunately, they changed the usage message in a different way than the way you changed the usage message. Git was therefore unable to combine your change and their change.If you were to look at the copy of
main.pyin your work-tree, this copy would have conflict markers in it, showing your change (fromH) and their change (fromT). If you setmerge.conflictStyletodiff3, the file would also show what the conflicting lines looked like in theBversion of this file.What
git mergetoolwill do is fish out the three input versions of the file: the one from commitB, the one from commitH, and the one from commitT. (These are not in the work-tree but are easily available togit mergetool.) It will then invoke your chosen merge tool on these three files as well as the work-tree copy. Your job is to update the work-tree copy so that it contains the correct merge resolution, whatever that is.The mergetool command repeats this for each conflicted file. It marks the file as properly resolved once you exit your merge tool (though there are various safety checks since not every tool reports this information correctly). The mergetool commmand stops when there are no conflicted files left. It can only be used while there are conflicted files.
Hence, to do a merge, you must:
git merge, perhaps with--no-commitif you want to inspect the result even if Git thinks Git got it right;git mergetool; andgit merge --continue(orgit commit) to tell Git to finish the merge. You will also need to supply a merge commit message, just like you supply any commit message, although you can use the (relatively low quality) default thatgit mergebuilds on its own (and most people mostly do).If the merge does not stop after step 1, it will go on through step 3 on its own unless you use
--no-commit.Once the merge is complete, you end up with this:
where new merge commit
Mhas the old tip commit commitHas its first parent and commitT(from their branch) as its second parent. Your branch name now points to the new merge commit.