gitgit-bashgit-mergegit-rebasekdiff3

$REMOTE point to different branches in git merge vs. rebase?


I want to configure kdiff3 to use a specific order for windows (from left to right): $REMOTE | $BASE | $LOCAL. However, I encountered an issue where $REMOTE differs between merge and rebase commands.

I configured GitBash with the following command:

git config --global mergetool.kdiff3.cmd "\"C:/Program Files/KDiff3/bin/kdiff3.exe\" \"\$REMOTE\" \"\$BASE\" \"\$LOCAL\" -o \"\$MERGED\""

enter image description here

Here are the steps I followed:

  1. Active Branch: temp2

  2. Merge Command: git merge temp1

    enter image description here

  3. Rebase Command: git rebase temp1. The $REMOTE and $LOCAL windows switched places: enter image description here

  4. Rebase Command: git rebase --onto temp1 head~1. This command also resulted in the $REMOTE and $LOCAL windows switching places: enter image description here

I've been trying to solve this configuration issue for a long time but haven't succeeded. Can someone explain what's going on and how to ensure that $REMOTE always refers to temp1 in both merge and rebase operations?


Solution

  • You can't do what you're asking. (Or, if you can, it would probably be a tool specific change rather than a Git related change.)

    The reason Git can't do this is because the indicators $REMOTE and $LOCAL don't represent specific branches, but instead represent "incoming" and "current", respectively.

    When you're merging, "incoming" and "current" are well-named and obvious, with "current" being your currently checked out commit or branch (temp2), and "incoming" is the commit or branch you are merging in (temp1).

    But when rebasing, behind the scenes, you're actually checking out the other branch first (or the commit specified by --onto) , and then cherry-picking each of the commits from your (previously) checked out branch. A cherry-pick is itself basically like merging the changes from a single commit, and at the moment of that paused merge, "current" is now the checked out commit (temp1) and "incoming" is the commit from the branch you are rewriting (temp2).

    To help conceptualize this, imagine that instead of rebasing, that you checked out temp1 and started cherry-picking each of the commits from temp2. If you look at the merge during one of those cherry-picks it becomes more intuitive that the commit you are cherry-picking is "incoming", just like when merging. Next time you do this, I'd recommend actually mentally converting the rebase to a series of cherry-picks, and perhaps it will feel more natural for the incoming commits from your temp2 branch to be on right, just like when merging temp1 into temp2.