Update - I do want to go ahead and agree with others that a workflow that leads to this probably isn't the best workflow.[1] But everyone's so busy harping on that, not a lot of people are providing practical answers about how you get from where you are to where you want to be. So:
The stash information is stored in a collection of commits, plus a ref with a heavily manipulated reflog. Dealing with the reflog will be the hardest part of what you're asking.
Not only is the reflog considered a local data structure (so no built-in behavior exists to share it), but each repo presumably has a conflicting reflog representing the local stack of stashed states, and the question of how to combine them is not straightforward.
One approach might look something like this. I'll call the repo you're dropping source
, and the one you're keeping target
.
First, create easily-shareable refs at each stash state in source
.
$ cd /path/to/source
$ git tag stash-s0 stash
$ git tag stash-s1 stash@{1}
$ git tag stash-s2 stash@{2}
// etc.
You also need to make notes of all of the stash messages. They're in the stash reflog.
$ git reflog stash
1111111 stash@{0}: Custom Stash Message Here
2222222 stash@{1}: WIP on master: 1234567 2
(You could store those as annotations on the tags, but IMO that's really no more convenient than anything else...)
Now you need to copy those tags (and their history) to target
; that will ensure that all stashed data is present
$ cd /path/to/target
$ git fetch --tags file://localhost/path/to/source
(file://localhost/path/to/source
is one possible URL for source
, assuming it's locally accessible from target
; you could use any git URL, or if source
is already a configured remote of target
, you can use the remote name instead of the url.)
Now comes the tricky part; you need to rebuild the stash
reflog on target
.
First you need to keep track of any entries already in target
s stash
reflog. You can do this with tags, the same as the stashes from source
.
$ git tag stash-t0 stash
$ git tag stash-t1 stash@{1}
// etc.
And, again, make note of existing stash entry messages
$ git reflog stash
3333333 stash@{0}: WIP on master: 7654321 2
Then you can remove the stash ref. Normally I wouldn't circumvent the git interfaces but in this case, it's not like there's a "safe" way to do it.
$ rm .git/refs/stash
$ rm .git/logs/refs/stash
And finally you can build the new stash stack. Your first command will be
$ git update-ref --create-reflog -m "<stash-message-1>" refs/stash <tag-name-1>
or, on new enough versions of git
$ git stash store -m "<stash-message-1>" <tag-name-1>
where <stash-message-1>
and <tag-name-1>
are the stash message you recorded for what will now be the last (oldest/"bottom") stash on the stack, and the tag you used to preserve that stash state, respectively. Each subsequent command will be
$ git update-ref -m "<stash-message-n>" refs/stash <tag-name-n>
or
$ git stash store -m "<stash-message-n>" <tag-name-n>
progressing "forward through time" in the list of stashes.
And then you can do away with the tags you used.
$ git tag -d stash-s1
// ...
[1] It's feasible in git to create temporary branches then use interactive rebase as needed to clean the history up as you finally are ready to migrate it onto a "real" branch. And a stash is just as "heavy-weight" as real commits anyway, because a stash is real commits. A stash is great to push some changes out of the way for a minute so you can use your worktree for something else real quick, but a long-lived stash isn't the best thing.