3

Assume we have a file common_ancestor (master)

ok
ok
ok
ok
ok

From there, we change and commit master to

ok
change not ok (looking back)
ok
ok
ok
latest change
ok

Now we have a better idea, checkout common_ancestor and change it to

ok
ok
ok
This is a really good change
ok
ok

and commit in a new branch dev. As I need some developments from master, I want to merge dev into master but I want to decide for every change whether to keep or not. I tried

git checkout master
git merge dev --no-ff --no-commit

But I did not get what I expected. What I am looking for is something like:

ok
<<<<HEAD
change not ok (looking back)
====
>>>> HASH
ok
ok
<<<<HEAD
====
This is a really good change
>>>> HASH
ok
<<<<HEAD
latest change
====
>>>> HASH

where conflict markers are visible (see here).

Edit: What I have seen, git merge dev --no-ff --no-commit does not highlight the changes - @VonC explained why there are no conflict markers visible (because there are no conflicts!).

Christoph
  • 6,841
  • 4
  • 37
  • 89
  • Perhaps a duplicate of http://stackoverflow.com/questions/5235010/how-to-prevent-an-automerge-using-git – Dunno Sep 15 '16 at 11:47

3 Answers3

2

In your case, merging dev to master would simply:

  • add the change from dev "This is a really good change"
  • keep the change introduced in master "change not ok (looking back)"

That is because those changes were not made at the same spot in the file: there is no concurrent modification at the same line.
That means there is no conflict.

If you want to have a look after a merge (but before the merge commit), you can set up a custom merge driver.

[merge "verify"]
        name = merge and verify driver
        driver = ./merge-and-verify-driver %A %O %B

You can associate that driver to your files in a .gitattributes file.

*.R merge=merge and verify driver

With merge-and-verify-driver.sh a script which always return 1, in order to indicate that there was a conflict, even if the merge was actually resolved without conflicts (which is the case here: no conflict in your merge).

#!/bin/bash
git merge-file "${1}" "${2}" "${3}"
exit 1

Note: In case of conflicts, you will have more information with:

git config --global merge.conflictstyle diff3
Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • To see an example of concurrent modification: http://stackoverflow.com/a/38989749/6309 – VonC Sep 15 '16 at 11:48
  • I understand the missing conflict markers now. What if all my files are `.R` files? How can I tell git that, for a specific file, I would like "to review" first? If I understand the answer in your link correctly, they specify a file extension in the git attributes. Is a custom command like `git merge --verify dev` possible? (I appologize, if the question is stupid - I am quite new to git.) – Christoph Sep 15 '16 at 13:04
  • @Christoph In a .gitattribute, you can associate your custom merge driver to a category of files (as in https://gist.github.com/dpwright/2657379) I have edited my answer. – VonC Sep 15 '16 at 13:14
  • But then, all my `.R` files "need to be reviewed", that is, I cannot decide whether I want to have a look at a merge or not? (Backround: In most(!) cases git does exactly what one would like - it would be really bad if I make git worse / slow) – Christoph Sep 15 '16 at 13:22
  • @Christoph Actually, with that merge driver, the merge will occur, not the merge commit. That gives you the opportunity to review only the files you want, before adding and committing everything. – VonC Sep 15 '16 at 13:23
  • @Christoph just to be clear: the merge will not stop at each files. It will merge all files, then stop in "failure" (exit 1). Then a git status will indicate if there are any conflicts. And if not, you can review the files you want. – VonC Sep 15 '16 at 13:25
2

As @VonC pointed out, it is not correct to treat differences in two versions as conflicts. Therefore he answered my question. To reach my goal I used

git difftool -t=kdiff3 dev master

and the merge tool therein. In kdiff3, every difference is highlighted and you can choose which version for each line you want to keep. See also here for a video-tutorial.

Christoph
  • 6,841
  • 4
  • 37
  • 89
  • Yes, kdiff3 is useful here. Once the merge is completed (but not committed), you can use git diff on any modified file, and kdiff3 will allow you to complete the merge if needed. – VonC Sep 16 '16 at 11:56
0

I want to merge dev into master but I want to decide for every change whether to keep or not.

That calls for an interactive rebase:

git branch dev_rebase dev
git checkout dev_rebase
git rebase -i master

Then go ahead from there. git help rebase, looking for "interactive mode" should give you ideas. Simply delete lines (commits) you want to skip, and use edit if you want to take parts of a commit but need to edit the files.

If something goes horribly wrong, dev will be untouched, in any case.

# if happy:

git checkout master
git merge --no-ff dev_rebase

# for good measure:

git checkout dev
git rebase master
AnoE
  • 8,048
  • 1
  • 21
  • 36
  • I fear I didn't work long enough with git: How do you proceed? When I type your command in git bash, a strange editor (MINGW64) opens and I am lost. See edit... – Christoph Sep 15 '16 at 19:40
  • In that editor, git lists all commits (from master to the tip of your current branch). If you just exit it, git will replay all commits and you will end up where you started. The magic is in editing that file - you can delete lines (those commits will be skipped), you can reorder them (commits will be applied in the different order), or you can replace the command `pick` by something else, like `edit`. `git help rebase` explains it in greater detail. – AnoE Sep 16 '16 at 10:28
  • I think your approach is different as rebase also does the merge for you - See my answer below and what I did in the end. Please let me know if I am wrong, then I will have a look at it again. – Christoph Sep 16 '16 at 11:49