6

I'm merging two git changesets (or perhaps - in the process of git rebase'ing, which merges changesets) involving file foo, and have some merge conflicts. The file looks like so:

text appearing in all changesets
<<<<<<< HEAD
text added on the head
=======
something else added on another changeset
>>>>>>> 1babf8ed... commit comment here
more text appearing in all changesets
added text, no conflicts
yet more appearing in all changesets

My question:

For a specific file (like foo above) How can I display the conflicts contents so that the HEAD revision shows up as removed text, and the other changeset (in my example) shows up as added text? In other words, how can I make some tool treat the part between <<<<< and ===== as prefixed by - and the part between >>>>> and ===== as prefixed by +, or the other way around?

Notes:

  • The best thing would be just diff-like output to the standard output stream, because I could pipe that into another tool. But something with more tie-in to git's diff-related tooling is also relevant. I would rather not have to download some custom utility/app if I can reasonably avoid it.
  • A side-by-side display of the HEAD and other-commit versions is also useful
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 1
    @evolutionxbox: Please don't bait me into being off-topic. I'm asking how to resolve a problem I'm having, not for tool recommendations. And I am talking about my scenario, which, indeed, involves git. I hope to actually _not_ need additional software to do this. – einpoklum Jan 07 '19 at 10:29
  • 1
    I was likely out of line, but you _did_ use the words "how can I get some tool". I just wanted clarification. – evolutionxbox Jan 07 '19 at 10:32
  • @evolutionxbox: Rephrased that bit, although I think it was clear enough before as well. – einpoklum Jan 07 '19 at 10:35
  • You are probably right, but that phrase just caught my eye. Hopefully on a more helpful note, https://stackoverflow.com/questions/7669963/how-can-i-get-a-side-by-side-diff-when-i-do-git-diff has a lot of suggestions on this matter. – evolutionxbox Jan 07 '19 at 10:40
  • @evolutionxbox: Those suggestions are on another matter, and it's difficult to understand whether any of them will do what I want. If you can point out something specific that would be awesome. – einpoklum Jan 07 '19 at 10:46
  • @einpoklum have you tried setting up a mergetool (ie vimdif, meld, kdiff3)? What tool you can use depends on your environment and liking. For info `git help mergetool`. – joran Jan 07 '19 at 12:12
  • @joran: mergetool shows me the the non-conflicting differences as well. Can I get it to just show what I asked for? – einpoklum Jan 07 '19 at 12:24
  • vimdiff has "next difference" keystrokes. `]c` to jump to the next change, `[c` the previous. – jthill Jan 07 '19 at 14:08
  • @jthill: How does this address my question? – einpoklum Jan 07 '19 at 14:24
  • 1
    As far as I know, there is no tool to do this. You could write a post-processing filter, but it might be simplest for you to extract the `HEAD` and other-commit versions of the file from the index (these are in index slots 2 and 3 respectively) and just run a unified diff on them. Note that this ignores the crucial *third* (first?) input, which is the merge base version of the file in slot 1. – torek Jan 07 '19 at 15:08
  • @einpoklum, depends on which tool you use, i.e. with meld you could use `--auto-merge` to apply all non-conflicting changes (see https://lukas.zapletalovi.com/2012/09/three-way-git-merging-with-meld.html). I'm on osx so meld is not an option, sadly (but the IDE that I currently use has similar support for resolving conflicts) – joran Jan 07 '19 at 15:14

2 Answers2

1

Conflicts aren't diff as it is not additions on a side, and deletion on the other one.

That being said, tools like meld, kdiff3, or p4merge are able to display conflicts in "side by side" view to help you fix them.

Edit:
For example:

Given the situation created through this script:

#!/usr/bin/env bash

git init demoRepo
cd demoRepo
git commit --allow-empty -m "Init"
for i in {1..10}; do
  echo $i >> myFile.txt
  git commit -m "Add ${i} to my file" -- myFile.txt
done
git checkout -b branch2 HEAD~5
for i in A B C D E; do
  echo $i >> myFile.txt
  git commit -m "Add ${i} to my file" -- myFile.txt
done
git merge master

We have a conflict inside myFile.txt.

Set meld to be your mergetool with:

git config --global merge.tool meld
# Use `--local` if you want this setting to be only in current repository

Then call it with:

git mergetool
# You may also call it without (pre)defining the tool in config, like:
#   git mergetool --tool=meld

Meld should know display you conflict with a "side by side" view.

meld for conflict resolution

mab
  • 378
  • 1
  • 8
  • I don't think this answers my question. Additionally, can you be more specific about how these tools (or at least meld) can do this, given only a single file? – einpoklum Jan 30 '19 at 00:06
  • I've edited my original answer with example as it seems to be not clear enough at first. – mab Jan 30 '19 at 08:17
1

Edit: git diff will show all diffs between the two revisions, which may include a lot of diffs that don't cause a merge conflict. If you want to show merge conflict diffs only, I don't have a solution yet.

If you're willing to see all diffs between the two revisions, you can simply use git diff. You'll need to pass it:

  • Treeish (eg, the SHA1 handle) of the commit on one side of the merge (to treat as "-")
  • Treeish of the commit on the other side of the merge (to treat as "+")
  • Optionally, the filename to diff
  • Optionally, -U999999 to show the entire file (by telling it you want that many lines of context around any difference)

Example: git diff a829c71 d98ef2a -U999999 example.py

krubo
  • 5,969
  • 4
  • 37
  • 46