0

I want to write a shell script, so that I can schedule a merge between two branches to happen at a specific time. However, since I might be working in another branch when that time is reached, I need it to happen in the background.

So, is there a simple way to merge branch A into branch B, without having to checkout B first?

jthill
  • 55,082
  • 5
  • 77
  • 137
Benubird
  • 18,551
  • 27
  • 90
  • 141
  • Duplicate of [Merging Branches Without Checkout](http://stackoverflow.com/questions/4156957/merging-branches-without-checkout) –  May 21 '14 at 17:27
  • Duplicate of https://stackoverflow.com/q/10637584/4138912. – doak Dec 20 '18 at 23:29

2 Answers2

2

A true (non fast-forward) merge is performed using the index—this is because in case of a conflict in a file you have to store the base and the both sides of that files in the index entry for it. git merge, being a porcelain command, also touches the work tree, but this is not required for the plumbing-level commands. So, to merge A into B you will need at least a separate index.

So you have these two options:

  • Use the git-new-workdir contrib script to turn arbitrary directory into a "shim" repository which has its own work tree, HEAD and the index but uses the object storage of the original Git repository.

    IMO, this is the simplest way unless you want to script the task to repeat it multiple times.

  • Use plumbing Git commands and environment variables to cook an environment suitable for performing a merge.

    You might either set aside the index and the work tree and perform a normal merge using git merge there; this, while deals with some other problem, explains how to set up separate index and work tree.

    Or you can pick a more hardcore route and use only the separate index and plumbing-level commands to perform an index-only merge. The key commands to do that (after setting a separate index aside) are:

    • git read-tree -m which perform an actual merge, and
    • git write-tree to make a tree object out of the index, and
    • git commit-tree to create a commit referring to that tree object.
Community
  • 1
  • 1
kostix
  • 51,517
  • 14
  • 93
  • 176
  • 1
    See [this answer](https://stackoverflow.com/a/53876246/4138912) for an example script using the "worktree" approach. Btw., in the meantime `git worktree` is available, hence no need for `git-new-workdir` from contrib. – doak Dec 20 '18 at 23:27
1

You've got a worktree you want to protect, use another worktree. git clone's cheap, it's built for this:

temp=$TMPDIR/temp
git clone -s . $temp -b B
( cd $temp; git merge origin/A && git push ) && rm -rf $temp

If there's merge conflicts temp won't be deleted, fix them, push, rm.

If you've got B checked out at the time the push will fail, git pull $temp when you're ready.


The clone will do a full checkout, which merge doesn't actually need to do its work. It's easy to avoid,

git clone -s . $temp -b B --no-checkout   # < add --no-checkout
cd $temp
git read-tree HEAD                        # < add read-tree HEAD
git merge
# ...
jthill
  • 55,082
  • 5
  • 77
  • 137
  • Good answer, but I think I would prefer to put the temporary clone somewhere outside of my repository, just in case of name clashes or other messiness... – twalberg May 21 '14 at 15:56