Given your requirement to not have to clean your working directory, I assume you mean that you don't want to have to clean either your working tree or index, even via some scripting. In that case, you won't find a solution within the bounds of your current local repo. Git uses the index extensively when merging. I'm not sure about the working tree if there are no conflicts, but in general, merging is inextricably tied to the currently-checked-out branch.
There's another way, though, that wouldn't require you to change anything in your current repo. It does, however, require you to have or create a clone of your repo. Basically, just clone your repo, then do your merge in the clone, and push it back to your original repo. Here's a brief example of how it would work.
First, we need a sample repo to work with. The following sequence of commands will create one. You'll end up with master
as your current branch and two other branches with changes ready to be merged named change-foo
and change-bar
.
mkdir background-merge-example
cd background-merge-example
git init
echo 'from master' > foo
echo 'from master' > bar
git add .
git commit -m "add foo and bar in master"
git checkout -b change-foo
echo 'from foo branch' >> foo
git commit -am "update foo in foo branch"
git checkout -b change-bar master
echo 'from bar branch' >> bar
git commit -am "update bar in bar branch"
git checkout master
Now, imagine that you're working on master
, and you're wanting to merge change-bar
into change-foo
. Here's a semi-graphical depiction of where we are:
$ git log --oneline --graph --all
* c60fd41 update bar in bar branch
| * e007aff update foo in foo branch
|/
* 77484e1 add foo and bar in master
The following sequence will accomplish the merge without interfering with the current master branch. Pack this into a script, and you've got a nice "background-merge" command:
# clone with absolute instead of relative path, or the remote in the clone will
# be wrong
git clone file://`realpath .` tmp
cd tmp
# this checkout auto-creates a remote-tracking branch in newer versions of git
# older versions will have to do it manually
git checkout change-foo
# creating a tracking branch for the other remote branch is optional
# it just makes the commit message look nicer
git branch --track change-bar origin/change-bar
git merge change-bar
git push origin change-foo
cd ..
rm -rf tmp
Briefly, that will clone the current repo to a subdirectory, enter that directory, do the merge, then push it back to the original repo. It removes the subdirectory after it's done. In a large project, you might want to have a dedicated clone that's just kept up to date instead of making a fresh clone every time. After the merge and push, we end up at:
$ git log --oneline --graph --all
* 24f1916 Merge branch 'change-bar' into change-foo
|\
| * d7375ac update bar in bar branch
* | fed4757 update foo in foo branch
|/
* 6880cd8 add foo and bar in master
Questions?