412

I need a way to export a stashed change to another computer.

On computer 1 I did

$ git stash save feature

I'm trying to get the stash patch to a file and then import it to another computer

$ git stash show -p > patch

This command gives me a file that I can move to another computer where this repo is cloned, but the question is how to import it as a stash again.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Marcelo A
  • 4,831
  • 4
  • 19
  • 12
  • 9
    fyi `git stash save` is now deprecated in favour of `git stash push` – Ewan Aug 11 '19 at 11:13
  • 2
    Unfortunately, `git stash show` ignores untracked files, even if they are stashed. – Andrzej Wąsowski Jun 08 '21 at 06:46
  • 6
    @AndrzejWąsowski crazy timing: two days before your comment, `git 2.32.0` was released with `[-u|--include-untracked|--only-untracked]` for `git stash show`. My substitute commands for those in the question are now `git stash push --include-untracked` and `git stash show --include-untracked --patch > patch`. – Ben Mares Aug 16 '21 at 19:10

13 Answers13

354

You can apply a patch file (without committing the changes yet) by simply running

git apply patchfile

Then you can simply create a new stash from the current working directory:

git stash
poke
  • 369,085
  • 72
  • 557
  • 602
  • 40
    After reading this answer one thing I was wondering was how to select a particular stash from all my stashes. The answer to that is here: http://stackoverflow.com/a/1910142/1148702 . In this case I ended up doing: `git stash show "stash@{0}" -p > patch` instead of the OP's second shell command. – Tim Arnold Mar 16 '16 at 15:03
  • I have my patch file correctly with the diff but when I apply it in the new repository nothing happens! – Arash Oct 19 '16 at 21:57
  • 1
    @TimCamber i don't think you need the double quotes around `stash@{0}`.. – ari gold Aug 17 '17 at 21:15
  • 2
    @arigold Depends on the shell you’re using. For example in PowerShell, you need them since curly braces are a special syntax there. – poke Aug 17 '17 at 21:24
  • Note that this method only works if the files that the patch file applies to exist in the working tree. Otherwise, `git apply patchfile` will fail. – LarsH Mar 29 '18 at 14:08
  • 4
    If someone get error "git patch does not apply" please try this `git apply --reject --whitespace=fix mychanges.patch` – rishiehari Oct 22 '18 at 22:20
  • What if there're binary files in the stash? – Opux Apr 11 '19 at 14:12
  • @Opux Same as when you try to do a merge that includes binary files: Either the path applies properly, or you will get a conflict which will tell you that it couldn’t apply the patch for that file. You can then do whatever to resolve it. – poke Apr 11 '19 at 15:35
  • 2
    @rishiehari VERY NICE!! I had a bunch of `patch does not apply` and `cannot apply binary patch to my_file.aar without full index line` and `git apply --reject --whitespace=fix mypatchfile` did a decent job. It still had trouble with two files, but I can manually copy those files – Someone Somewhere Aug 08 '19 at 23:48
  • 1
    WARNING: if you stashed untracked files, they will not be present in the patch. – Someone Somewhere Aug 09 '19 at 00:04
119

You can create stash as patch file from one machine,then can share that patch file to another machines.

Creating the stash as a patch

$ git stash show "stash@{0}" -p > changes.patch

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.

Applying the patch

Now transfer that stash to another machine and paste it into the root folder of your project. Then run this command

$ git apply changes.patch

If there is mistake and you want to reverse the change

$ git apply changes.patch --reverse
Simran
  • 2,364
  • 1
  • 12
  • 19
  • 1
    I had to replace the '-p' argument with '--binary' to get this to work properly – Farhan Haider Oct 22 '20 at 07:26
  • 2
    I get the error `patch does not apply` when I try to apply the patch on the same computer I created. – TheCrazyProgrammer Mar 01 '21 at 17:52
  • @TheCrazyProgrammer Did you run `git apply changes.patch` or `git stash apply changes.patch`? The former works, the latter gives me errors (with or without using `<` to read the file as input). – yuyu5 May 24 '21 at 18:06
  • 2
    @TheCrazyProgrammer use `git apply --3way changes.patch` to try to solve conflicts later, if you have got "patch does not apply". More info: https://stackoverflow.com/questions/4770177/git-patch-does-not-apply/47756467#47756467 – epineda Aug 16 '21 at 23:35
  • wasn't working when the diff was to create new files as well – Aryeh Beitz Oct 20 '21 at 11:41
  • I fail to see the essential difference between this answer and https://stackoverflow.com/a/3973058/6607497 – U. Windl Mar 29 '22 at 13:27
  • Don't forget to add `-u`, e.g. `git stash show "stash@{0}" -u -p > changes.patch` if your stash has untracked files. – user9645 Oct 17 '22 at 18:07
  • I have over 60 stashes – Boris Verkhovskiy Oct 26 '22 at 22:13
23

alternatively you can create a branch from your stash (on computer 1), using

git stash branch stashed_changes_branch

commit your changes:

git commit -a

then add it as a remote on computer 2:

git remote add pc1 user@computer1:/path/to/repo

now you can retrieve the remote information using

git fetch pc1

now you can import the commit in the way you want; using git cherry-pick, git rebase or whatever you like... If you want it to look like you just did git stash apply; you can use git cherry-pick --no-commit.


If you have no direct connection between computer1 and computer2; you can use a remote (like github or something similar):

git push origin stashed_changes_branch

and on computer2:

git fetch
Chris Maes
  • 35,025
  • 12
  • 111
  • 136
  • 2
    This assumes that the source system (computer1) is open to receive external connections which for most people landing here is not likely to be true. If you want to go the branch route why not just push a temp branch to remote origin and pull that from computer2? You can delete the remote branch as soon as you have pulled if you don't want to keep it around. Branches in git are so cheap there's usually few reasons to not use them. – indivisible Sep 27 '16 at 06:45
  • @indivisible I disagree there are lots of opportunities to connect two computers on the internet today. The technique described in the answer might be useful transferring a work in progress from a laptop to a desktop on a LAN. Even a virtual vpn service like Hamachi would be used to transfer files over the internet anywhere directly between computers running git. – steampowered Jul 18 '17 at 13:41
  • 4
    @steampowered, sure it _may_ be true for some people/situations but I thought it a point worth noting for future readers as it is a hard requirement for this solution to work and modifying your local env/system to accept incoming traffic takes non trivial configuration that, in my opinion, is "overkill" for a task like this. If your system(s) are already open then by all means use this answer - it's not incorrect. I just feel that the majority of users landing here won't be in a situation like that. – indivisible Jul 18 '17 at 13:52
  • Stashes are commit objects and thus already have a commit hash (see `git stash list --oneline`), so you don't technically have to apply the stash to a new commit object. In other words, creating a new branch isn't necessary. However, pushing a stash directly to a remote is tricky to say the least. – Tyler Crompton Jul 31 '17 at 08:48
23

Alternatively, you can copy the entire local stashes(+ other local branches, local tags, etc) to another computer as follows:

  • git pull on both your old and new git directory to ensure that both have the latest changes (Or make sure that both repos have the same HEAD using git reset --hard commit-hash).
  • copy the .git folder from the old git directory to the new repository
shafeeq
  • 1,499
  • 1
  • 14
  • 30
  • 1
    Although the compressed tar of .git was 700M+, this turned out to be far easier than the other proposed solutions, especially since I had multiple stashes. – Chris Warth Apr 26 '19 at 21:17
12

A stash is a special merge commit of the work tree between the base commit and the index. One way could be to save each as separate patches, checkout the stash first parent, restore the index and work tree from the two patches and finally restore the stash (it seems one answer goes this way).

This is needed to fully recreate all information from the stash, and if you don't care about that you should at the very least checkout the stash's first parent before restoring to avoid conflicts and keep track of where the stash was created.

This is what I did to fully restore all stashes from one repo to another. If you can't have them on the same computer, you can save the stash tags in a bundle after creating them and copy the refs list and bundle to the target computer.

From the root of the original repo:

  1. Get the list of stash refs
  2. Tag your stash refs so you can retrieves them with git fetch (the tag names doesn't mater, change it if there is a conflict. I used stash_ + the number(s) in the logical stash ref)
  3. Convert the logical refs to sha1 hashes in reverse order - we'll use them later
  4. Save that repo path - also for later
refs=$(git stash list|cut -d: -f1)
for ref in $refs; do git tag stash_${ref//[^0-9]} $ref; done
refs=$(git rev-parse $refs|tac)
oldpath=$PWD

NB: This requires bash or compatible shell (ksh, zsh should do...) You could also increment a variable, ex stash_$((i++)) if your shell doesn't support ${param//pattern}

Now in the new repo, for each ref:

  1. Fetch the ref from the old repo (we don't even need to use the tag names, because we have tagged them we can retrieve them with git fetch)
  2. Re-import the stash from the ref, using that ref's subject as the stash message.
for ref in $refs; do git fetch $oldpath $ref; git stash store -m "$(git show -s --pretty=%s $ref)" $ref; done
Thomas Guyot-Sionnest
  • 2,251
  • 22
  • 17
  • This was really useful, I did a variation of this just now to migrate my stashes to a new machine, with a couple of minor amendments for the places we obtain the stash names and shas `refs=$( git stash list --format=%gd ) ... refs=$( git stash list --format=%h | tac )` – mattlaw Apr 22 '22 at 13:10
  • 1
    Note that since you can also use git fetch to retrieve a series of commits by its long hashes, one can avoid tagging the commits. ie. `hashes=($(git reflog --format=%H refs/stash)` gives you a list of commit hashes, that can be fetched with `git fetch $oldpath $hashes`, but one still has to loop over them for `git stash store`. – Jonas Hörsch Feb 16 '23 at 14:39
9

How to do export Stash in SourceTree:

  1. Make a new branch "StashTransfer" from a branch where you are going to use your Stash
  2. Apply your stash to it and make a commit

  3. Click on your commit and make a patch from it, take the patch file with you.

  4. Go to a different repository, select the same parent branch which you just used in 1)

  5. Actions / Apply Patch, select Mode: Modify working copy files, push Apply Patch now you have uncommitted modifications from the patch in your current working environment

  6. Make a new Stash for the current repo

Venkataraman R
  • 12,181
  • 2
  • 31
  • 58
KEMBL
  • 536
  • 6
  • 10
7

Another option is to rsync the .git folder from one computer to another computer. rsync processes only file changes (faster than a copy).

One downside to this approach is the configs would also be overwritten, which may not be desired if you run different .git configs between the two machines. But you could overcome this by excluding files with the --exclude option in rsync.

Overall I think a native Git solution is cleaner, but this rsync hack could be nice for someone in a hurry who might be more familiar with rsync than git.

steampowered
  • 11,809
  • 12
  • 78
  • 98
7

git --no-pager stash show -p > patch

Copies the stashed changes to patch file

git apply path/to/the/patch/file

Applies stash from the patch file

Following shell script allows users to copy all stashes from one folder to another folder. https://gist.github.com/senthilmurukang/29b55a0c0e8694c406991799153f3c43

5

The startup command from the original post:

git stash show -p stash@{x} > patch_file

didn't work for me (for some reason it created unusable patch files). Instead I had to:

git stash apply stash@{x}
git commit

for each stash I wanted to transfer. Then, I placed the 'parent' repo within file:/// reach of the 'child' repo, and did the following, for each stash commit:

git fetch file:///path_to_parent_git && git cherry-pick commit_sha
git reset --soft HEAD^
git stash save my_new_stash_on_child

This is more complex but did the trick for me.

pizon
  • 51
  • 1
  • 2
3

Pay attention also to the local files stashed with option --binary, and several stashed when export and import. After searching a while, I did the following.

#check all the stashed

git stash list

#export stash by number, --option binary is important to export binary files

git stash show stash@{0} -p --binary > patch0

#import stash, go to new repository

git apply /old_repository/patch0

#Then re-stash the local changes

#repeat the process for all the stashes stash@{1}, ... ,stash@{n}

maoanz
  • 151
  • 1
  • 5
  • 15
0

If you want to move your changes from one machine to another you could always commit your changes on your machine and then do a soft reset on their machine.

Office

git commit -m "-stash-"

Kitchen

git reset --soft HEAD~1

Siriquelle
  • 201
  • 2
  • 5
0

Based on @Chris Maes answer

Running this NodeJS script on repo root may create a patch file for every existing stash:

const fs = require('fs');
const cp = require('child_process');

try{
    fs.mkdirSync('./stashes')   
}catch(err){console.log("Folder stashes already exists")}


var stashes = cp.execSync("git stash list").toString().split('\n');
for(var stash of stashes){
    var stashId = stash.split(":")[0];
    var patchFilename = stash.replace(/[/\\?%*:,|" <>]/g, '_');
    cp.execSync(`git stash show ${stashId} -p > ./stashes/${patchFilename}.patch`);
}
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 19 '22 at 11:00
0

This approach ensures a smooth transfer of work between computers while maintaining the version history.

The trick is that we commit the changes, push to remote, pull on destincation, create a patch from commit, and then revert the commit. from there we apply the patch that contains our changes.


Remember to replace your_branch_name with actual BRANCH name.


Step 1: Commit Changes on Source Computer:

git add .
git commit -m "WIP"

Step 2: Push Changes to Remote:

git push origin your_branch_name

Step 3: Pull Changes on Destination Computer:

git pull origin your_branch_name

Step 4: Create a Patch from last commit that just pulled:

git checkout your_branch_name
git format-patch HEAD^ -o .
git add .
git stash save "Patch"

Step 5: Revert the WIP Commit:

git reset HEAD^
git add .
git commit -m "revert WIP"

Step 6: Pop Stash and Apply Patch:

git stash pop
git apply --ignore-space-change --ignore-whitespace  0001-wip.patch

This sequence of commands allows you to export changes from one computer to another using Git's version control features. It involves committing, pushing, pulling, generating a patch, stashing, reverting, and applying the changes.

akokani
  • 870
  • 8
  • 18