2

We are merging branch A into branch B. In branch A we've removed some files. When merging into branch B we don't want to remove the files in branch B. We want the other merge changes except the file deletes. How can we do this?

Note there are no merge conflicts on the files in question (ie: they haven't been touched in branch B).

Marcus Leon
  • 55,199
  • 118
  • 297
  • 429

3 Answers3

3

Here a possible solution not depending on the deletes being in separate commits:

# Do all the merging but do not commit the result
git merge --no-commit branchA
# Look at what has changed
# Beside the list of modified files, there is also a list of all deleted files
git status
# Restore the deleted files (from the current commit on branchB)
git checkout HEAD -- file1 file2
# Now commit the merge
git commit

Instead of listing all deleted files one by one, this (not thoroughly tested) snipped can be used (inspired by this answer to another question):

git diff-index --cached --diff-filter=D -z --name-only HEAD | xargs -0 git checkout HEAD --
Community
  • 1
  • 1
siegi
  • 5,646
  • 2
  • 30
  • 42
  • This solution means the files are gone for a couple of seconds, which may or may not be acceptable. – Matthias Urlichs Jan 11 '17 at 04:27
  • @MatthiasUrlichs: If this is not acceptable, you could do the "merge and restore" in a clone of your repository, then `fetch` from it and do a fast-forward merge to the created merge commit. – siegi Jan 11 '17 at 07:00
0

I can think of two possible solutions:

  1. Rebase branch A so that all commits with deletions are at the "end" of the branch. Then merge the last commit before these deletions into Branch B. Of course, this might not be a viable solution if rebasing will cause problems with any cloned repos with work based on branch A.

  2. Merge with branch A directly then "undo" the commits with deletions with git revert. The disadvantage here is that you need to find which commits to "undo". If there are a lot of these, running git revert by hand will be very time consuming.

I apologize if neither of these work for you. I am just brainstorming some possibilities here. Hopefully others come up with better ideas.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
0

If you want to automate this you can tweak git-merge-one-file (it's in libexec/git-core wherever you've got git installed) and run the merge manually.

git merge --no-commit --no-ff -s ours $topic            # set up parents
git read-tree -um $(git merge-base @ $topic) @ $topic   # handle really trivial cases
git merge-index -o $tweaked_git_merge_one_file -a       # everything else, do my way

and the tweak is pretty easy, treat the $1$1. case, where your branch didn't do anything but the other branch deleted it, as for the .$2. case where you added it and the other branch didn't do anything. so

-"$1.." | "$1.$1" | "$1$1.")
+"$1.." | "$1.$1" )

and

-".$2.")
+".$2." | "$1$1." )

since in both cases the local copy of the file is correct as-is, the only thing to do is mark the index entry as (correctly) merged.

jthill
  • 55,082
  • 5
  • 77
  • 137