I wonder if there is the way to copy one commit to another branch without checking out that branch.
For example, I have two branches: master
and parallel_version
.
I'm on parallel_version
branch and I found a bug in file common for these branches.
I've fixed it and committed. How to duplicate this commit to another branch, assuming I'm using git-svn?
Normally I would do:
$ git checkout master
$ git cherry-pick parallel_version
$ git checkout parallel_version
Is there better way of doing that?
That's not possible - simply imagine what would happen if there was a conflict that couldn't be resolved automatically. For the same reason you also can't update branches that are not currently checked-out (even if a fast-forward was possible).
https://github.com/lennartcl/gitl provides "git cherry-copy" and "git cherry-move" scripts that do this and handle most of the corner cases.
Crazy idea (based on mnaoumov's comment) if you really want to avoid touching the checked out files (say you don't want to disturb your build system) … that's what I want anyway.
- Clone the whole git repo to a temporary directory.
- Do the work in the clone.
- Add the clone as a remote.
git fetch clone && git branch mybranch clone/mybranch -f
- Clean up.
This would be a thing to automate. If you have filesystem snapshots, cloning the whole repo is cheap – perhaps not so crazy after all…
Here's a small script that creates a temporary clone of the repository, as suggested by user2394284:
/usr/bin/git-tmp-clone or ~/bin/git-tmp-clone
#!/bin/bash
# Unique name for the temporary clone.
totalhash=$(tar -c $(git rev-parse --show-toplevel)/.git | sha256sum | head -c8)
tmprepo="/tmp/$(basename $(pwd))_${totalhash}"
git clone . ${tmprepo}
# Start an interactive shell in the clone. Pass any
# arguments as initial commands to be executed.
/bin/bash --init-file <(echo "cd ${tmprepo}; $@")
# Clean up the clone.
rm -rf ${tmprepo} && echo "Deleted ${tmprepo}"
(This script is less than robust, but it seems to work for me on Ubuntu.)
You can use this to cherry-pick e.g. the last commit on the current brach to another branch, by running
git-tmp-clone "git checkout TARGET_BRANCH
&& git cherry-pick $(git rev-parse --short @)
&& git push origin HEAD"
(Note that in this example, the rev-parse
is evaluated in the origin repository before the clone is created! That's why it points to the most recent commit. Adapt as needed.)