13

Is there a git merge command that merges another branch into the current branch, but doesn't change any files?

Or in other words, I want to create a new commit on branch A with:

  • The same tree (files) as latest commit on branch A
  • Parent commit should be latest commit on branch A
  • Other parent commit should be latest commit on branch B

Consider two long running branches one mine, one theirs. I want to merge their branch onto my branch, but since the code is effectively doing the same, I want to mark it as merged. The next time I'm merging again, it will not look back further than the merge commit that will be created in this process.

I know about -X mine/--strategy-option=mine but that will only kick in when there's an actual merge conflict. No added/deleted files should be applied on my branch.

Caramiriel
  • 7,029
  • 3
  • 30
  • 50
  • My first thought was `git merge --no-commit theirs; git checkout mine .` but that will still add added files in `theirs` unless I am mistaken. Maybe you could just manually modify `.git/MERGE_HEAD` and then commit without making any changes? (Not an answer -- don't know if it will work) – trent Sep 19 '17 at 21:59
  • 4
    You are describing `-s ours` (not `-X ours`, but `-s ours`, they are very different). – torek Sep 19 '17 at 22:16
  • @torek Neat, are you able to post that as an answer? – Caramiriel Sep 26 '17 at 06:52
  • Maybe better to just close as duplicate of https://stackoverflow.com/q/23762897/1256452 ? – torek Sep 26 '17 at 14:33
  • 1
    Not strictly a duplicate, but good enough for future reference. Once people hit this page, they'll be redirected to more information. Thanks. – Caramiriel Sep 26 '17 at 17:30

2 Answers2

7

If you're absolutely certain you don't want the theirs, you could perform the merge without committing, then checkout mine as-is, then complete the merge commit.

git merge --no-commit their-branch
git rm . -rf
git checkout HEAD -- .
git commit

The git checkout HEAD -- . will overwrite any conflicted or automatically modified files. Performing a git status at this point should reveal that nothing is modified, but that you are still mid-merge. The commit then completes your non-merge merge.

Edit: git rm . -rf

Originally, I had omitted any part of this workflow capable of removing entirely new files from theirs, as git checkout HEAD -- . would leave these intact.

The line git rm . -rf ensures that every file known to git at that time is removed. This will include removing any file which existed in theirs but not ours. We will then checkout only those from ours, and commit the resulting empty merge.

Robin James Kerrison
  • 1,727
  • 1
  • 15
  • 26
2

You can craft your own commit object with the details you desire. Here is how I do it manually

  1. git checkout A

    • Start on the A branch
  2. git cat-file commit A > mine.commit

    • This retrieves the current commit object to use as a starting point. It has most of what we want in our new commit object.
  3. git rev-parse B

    • You need the output from this for 4.
  4. Edit mine.commit in your favorite text editor

    • This is the file you will put the information that satisfy your requirements
    • The tree line remains unchanged - this is the state of your repository at this commit
    • The first parent line remains unchanged - this is the commit-id of your A branch
    • Add another parent line with the hash code printed from 3. above
    • Modify the author, committer lines if desired. Change the commit message at the bottom
  5. cat mine.commit | git hash-object -t commit --stdin -w

    • This writes the commit object into your database and prints out its commit-id.
  6. git merge --ff-only <output from hash-object above>

    • This should succeed and your A branch should be updated accordingly
Ben
  • 1,287
  • 15
  • 24
  • That `git hash-object` is pretty nifty, I'm going to remember this. I think this solution works well when there's a lot of conflicts. `merge -s ours` seems to want me to "resolve" the conflicts (there are none, because of 'ours'), so this would be the better option. For less conflicting merges, I'd recommend the `merge -s ours` option though. – Caramiriel Sep 26 '17 at 06:56
  • Absolutely, I would 100% suggest using `merge` commands over this manual process. This process I describe here is for when merge just doesn't want to do the job effectively, usually it works quite well. – Ben Sep 26 '17 at 16:12