git merge: Removing files I want to keep!

Viewed 74570

How can you merge two branches in git, retaining necessary files from a branch?

When merging two branches, if a file was deleted in one branch and not in another, the file is ultimately deleted.

For example:

  • A file exists in master when you make a new branch
  • you remove the file from master since we don't need it (yet)
  • you make changes in the branch to add a feature, which relies on the file existing
  • you make bug fixes in master (cannot be discarded)
  • you merge some day, and the file is gone!

How to Reproduce:

  1. Create a git repo with one file.

    git init
    echo "test" > test.txt
    git add .
    git commit -m "initial commit"
    
  2. Create a branch

    git branch branchA
    
  3. Delete the file in master

    git rm test.txt
    git commit -m "removed file from master"
    
  4. Make ANY changes in branchA that don't touch the deleted file (it has to be unchanged to avoid Conflict)

    git checkout branchA
    touch something.txt
    git add .
    git commit -m "some branch changes"
    

From here, any way I've found to merge these two branches, the test.txt file is deleted. Assuming we were relying on the file for branchA, this is a big problem.


Failing examples:

Merge 1

git checkout branchA
git merge master
ls test.txt

Merge 2

git checkout master
git merge branchA
ls test.txt

Rebase 1

git checkout branchA
git rebase master
ls test.txt
7 Answers

Same issue with git. Was working on a feature in a branch, then my job decided to sideline the feature for later. Thus the relevant feature files were deleted from master branch to allow app deployment without unnecessary files ... for the time being. Now my job needs me to finish the old feature and when I try to merge or rebase the old branch into the current master it deletes the files I need.

The quick solution is: Modify the files you need to keep in your feature branch, add and commit, and then merge with your master. This will now cause a merge conflict as opposed to deletion mode when merging. Now you can keep "our" changes to the files.

The problem is git sees the file deletion in HEAD as not being changed and will default into deletion mode. Specifically: deleted in master and modified in HEAD is outputted after you modify the files you need.

Reproduce the solution:

  1. Reset a branch to the older version with deleted files: git reset --hard origin/old_branch
  2. Modify the files you need to keep. Do not leave them the same.
  3. Merge your current master into the feature branch: git merge master

Automatic merge failed; fix conflicts and then commit the result.

  1. Keep "our" changes when fixing conflicts.
  2. git add . and git commit -m "fix deleted HEAD"
  3. Finish merging: git merge master

Instead reversing merging, you could checkout file(s) from just before commit into your current merged branch (user Todd's suggestion):

  git checkout <commit hash or branch name> -- path/to/file

For example,

  git checkout 08ac9cf08f -- classify.cpp

and then you could push your branch.

Related