Is it possible to push a git stash to a remote repository?

In git, is it possible to create a stash, push the stash to a remote repository, retrieve the stash on another computer, and apply the stash?

Or are my options:

  • Create a patch and copy the patch to the other computer, or
  • Create a minor branch and commit the incomplete work to that branch?

Solution 1:

Note: I've just rewritten this answer with 24 hours more git-fu under my belt :) In my shell history, the whole shebang is now three one-liners. However, I've uncondensed them for your convenience.

This way, I hope you will be able to see how I did things, instead of just having to blindly copy/paste stuff.


Here is step by step.

Assume is source in ~/OLDREPO containing stashes. Create a TEST clone containing no stashes:

cd ~/OLDREPO
git clone . /tmp/TEST

Push all the stashes as temp branches:

git send-pack /tmp/TEST $(for sha in $(git rev-list -g stash); \
    do echo $sha:refs/heads/stash_$sha; done)

Loop on the receiving end to transform back into stashes:

cd /tmp/TEST/
for a in $(git rev-list --no-walk --glob='refs/heads/stash_*'); 
do 
    git checkout $a && 
    git reset HEAD^ && 
    git stash save "$(git log --format='%s' -1 HEAD@{1})"
done

Cleanup your temporary branches if you will

git branch -D $(git branch|cut -c3-|grep ^stash_)

Do a git stash list and you will something like this:

stash@{0}: On (no branch): On testing: openmp import
stash@{1}: On (no branch): On testing: zfsrc
stash@{2}: On (no branch): WIP on sehe: 7006283 fixed wrong path to binary in debianized init script (reported as part of issue
stash@{3}: On (no branch): WIP on debian-collab: c5c8037 zfs_pool_alert should be installed by default
stash@{4}: On (no branch): WIP on xattrs: 3972694 removed braindead leftover -O0 flag
stash@{5}: On (no branch): WIP on testing: 3972694 removed braindead leftover -O0 flag
stash@{6}: On (no branch): WIP on testing: db9f77e fuse_unmount_all could be starved for the mtx lock
stash@{7}: On (no branch): WIP on xattrs: db9f77e fuse_unmount_all could be starved for the mtx lock
stash@{8}: On (no branch): WIP on testing: 28716d4 fixed implicit declaration of stat64
stash@{9}: On (no branch): WIP on emmanuel: bee6660 avoid unrelated changes

On the original repository, the same looked like

stash@{0}: WIP on emmanuel: bee6660 avoid unrelated changes
stash@{1}: WIP on testing: 28716d4 fixed implicit declaration of stat64
stash@{2}: WIP on xattrs: db9f77e fuse_unmount_all could be starved for the mtx lock
stash@{3}: WIP on testing: db9f77e fuse_unmount_all could be starved for the mtx lock
stash@{4}: WIP on testing: 3972694 removed braindead leftover -O0 flag
stash@{5}: WIP on xattrs: 3972694 removed braindead leftover -O0 flag
stash@{6}: WIP on debian-collab: c5c8037 zfs_pool_alert should be installed by default
stash@{7}: WIP on sehe: 7006283 fixed wrong path to binary in debianized init script (reported as part of issue #57)
stash@{8}: On testing: zfsrc
stash@{9}: On testing: openmp import

Solution 2:

It's not possible to get it via fetch or so, the mirror refspec is fetch = +refs/*:refs/*, and even though stash is refs/stash it doesn't get sent. An explicit refs/stash:refs/stash has no effect either!

It would only be confusing anyway since that wouldn't fetch all stashes, only the latest one; the list of stashes is the reflog of the ref refs/stashes.

Solution 3:

I'm a little late to the party, but I believe I found something that works for me regarding this and it might for you too if your circumstances are the same or similar.

I'm working on a feature in its own branch. The branch isn't merged into master and pushed until its finished or I've made commits that I feel comfortable showing to the public. So what I do when I want to transfer non-staged changes to another computer is:

  • Make a commit, with a commit message like "[non-commit] FOR TRANSFER ONLY", featuring the content you want transfered.
  • Login to the other computer.
  • Then do:

    git pull ssh+git://<username>@<domain>/path/to/project/ rb:lb

    The URL might differ for you if you access your repository in a different way. This will pull changes from that URL from the remote branch "rb" into the local branch "lb". Note that I have an ssh server running on my own computer, and am able to access the repository that way.

  • git reset HEAD^ (implies --mixed)

    This resets the HEAD to point to the state before the "[non-commit]" commit.

From git-reset(1): "--mixed: Resets the index but not the working tree (i.e., the changed files are preserved but not marked for commit) [...]"

So you will have your changes to the files in the end, but no commits are made to master and no need for a stash.

This will however require you to git reset --hard HEAD^ in the repository in which you made the "[non-commit]", since that commit is garbage.

Solution 4:

It's a little late, but this answer might help someone. I wanted to know this because I wanted to be able to push an in-progress feature/bug/whatever and work from the same point on another computer.

What works for me is to commit my in-progress code (in a branch that I'm working on alone). When I get to my other computer, do a pull, then undo the commit with:

git reset --soft HEAD^

Continue working as you were, with all your in-progress changes there, uncommitted, and unstaged.

Hope it helps.