Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

git

git-stash

People also ask

Are git stashes only local?

No. Stashes are local. $ man git stash : Use git stash when you want to record the current state of the working directory and the index, but want to go back to a clean working directory.

How do I push to a remote git repository?

In order to push a Git branch to remote, you need to execute the “git push” command and specify the remote as well as the branch name to be pushed. If you are not already on the branch that you want to push, you can execute the “git checkout” command to switch to your branch.

How do you push after stash?

checkout a new branch stash-XXX # 2. commit the current changes in that branch # 3. push the branch to the remote local locbr=${1:-autostash-XXX} git checkout -b $locbr git add . git commit -a -m "Automatically created commit" git push origin $locbr echo "Autocommitted changes in branch $locbr ..." }

Can you share git stash?

You can create stash as patch file from one machine,then can share that patch file to another machines. The “stash@{0}” is the ref of the stash.It will create patch file with latest stash. If you want different one use command $ git stash list to see your list of stashes and select which one you want to patch.


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

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.


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.


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.


There seems to be a very neat trick to solve this. you can use git diff > file.diff (and commit the file) , then restore the changes using git apply file.diff (from anywhere) to achieve the same result.

This was explained here as well.


The currently accepted answer is technically correct, you can't directly tell Git to push all your stashes to a remote, and then pull everything into your local stashes on another computer.

And while the currently top-upvoted answer should work, I didn't like that it creates a bunch of temporary branches, and that it requires manually checking out the stash commit and saving it as a stash, which can lead to issues like this comment mentioned, and leads to a duplicate On (no branch): On testing:. Surely there must be a better way!

So while you can't directly push stashes, a stash is just a commit (actually two commits), and per the git push man page you can push commits:

The <src> is often the name of the branch you would want to push, but it can be any arbitrary "SHA-1 expression"...

I chose to push the stashes to refs/stashes/* so that I wouldn't clutter up my remote with extra branches. So I can do that with:

git push origin stash@{0}:refs/stashes/$(git rev-parse --short stash@{0})

(The rev-parse command gets the short hash of the stash, which will be unique for the repo.)

Next, I need to fetch the stash from the other computer. Git only fetches branches by default, so I need to fetch the stashes specifically:

git fetch origin refs/stashes/*:refs/stashes/*

Now to convert the stash commit back into an actual stash. As mentioned, while I could just check out the stash commit, reset, and stash as usual, I don't like that it requires extra steps, or that it might not maintain the index state for the stash. I was looking online for a way to do that automatically, but my search-fu failed me. Finally I looked through the man page for git stash, where I found this:

create
Create a stash (which is a regular commit object) and return its object name, without storing it anywhere in the ref namespace. This is intended to be useful for scripts. It is probably not the command you want to use; see "save" above.

store
Store a given stash created via git stash create (which is a dangling merge commit) in the stash ref, updating the stash reflog. This is intended to be useful for scripts. It is probably not the command you want to use; see "save" above.

Since I already have the commit, store sounds like what I want. So I can do:

git stash store --message "$(git show --no-patch --format=format:%s <SHA>)" <SHA>

Replacing <SHA> with the stash that was just fetched.

(The git show command gets the commit message from the stash commit, to use as the message for the stash log.)

The stash now shows up as normal in my local repo:

$ git stash list
stash@{0}: On master: temp
...

To clean up the remote, the stashes can be deleted from the remote like so:

git push origin :refs/stashes/<SHA>

This method also has the benefit of being idempotent: if you run the push command again, it will report Everything up-to-date. The fetch command can also be safely run repeatedly. While the stash store will skip storing the stash if it is the same as the most recent stash, it doesn't prevent duplicates of older stashes. This can be worked around though, as I do in my git-rstash script, see below.


For completion, you can also easily push all stashes (with bash):

for i in $(seq 0 $(expr $(git rev-list --walk-reflogs --count stash) - 1))
do
  git push origin stash@{$i}:refs/stashes/$(git rev-parse --short stash@{$i})
done

or import all fetched stashes:

for stash in $(ls .git/refs/stashes)
do
  git stash store --message "$(git show --no-patch --format=format:%s $stash)" $stash
done

I've created a bash script that can be called as a subcommand (e.g. git rstash push 0) so I don't have to remember all this. git-rstash can be found here.