在存储库副本之间传输存储的更改

jme*_*e52 4 git git-stash

我有一个仓库的两个副本,每个副本都带着几十藏匿状态的(stash@{0},stash@{1},...).

我需要删除其中一个副本,并且我想将所有隐藏的更改从我要删除的副本传输到我将保留的副本.我想保留关于所有藏匿状态的父母和日期的所有信息,以及索引的状态.

我一直在阅读文档,我找不到任何简单/直接的方法来做到这一点.有可能吗?


更新1:我希望将更改保持为存储状态而不是提交的原因之一是,通过使用--index标志,我可以检索为提交和工作目录中的更改而暂存的更改.如果我创建一个提交,我也将破坏隐藏状态的信息,其中父,索引和工作副本彼此不同.我隐藏的状态通常对应于初步测试工作,这些工作远非可编译,没有准备好承诺,而且目前我没有时间经历数十个整理它们.


更新2:我想我知道如何查看我要备份的信息,例如,

$ git show stash{5}
commit eb5731e828f467dbe9214d0e6a350f33898c1363
Merge: c9608582 1d6cb78d
Author: Author <author@example.com>
Date:   Wed Sep 20 18:54:51 2017 +0100
Run Code Online (Sandbox Code Playgroud)

清楚地产生工作目录状态(commit行)和日期的id,并且Merge:行中的id是父提交id和索引的id.

我不知道的是如何将所有这些信息转移到存储库的第二个副本,作为它的新存储状态.


更新3:澄清:存储库的两个副本已经存储了状态.

Mar*_*ger 5

更新 - 我确实希望继续并与其他人一致认为导致这种情况的工作流程可能不是最好的工作流程.[1] 但是每个人都在忙着努力,并没有很多人提供关于你如何从你想去的地方到达你想去的地方的实际答案.所以:


存储信息存储在提交集合中,加上带有大量操作的reflog的ref.处理reflog将是您要求的最难的部分.

reflog不仅被认为是一个本地数据结构(因此不存在共享它的内置行为),但每个repo可能都有一个冲突的reflog表示本地堆栈状态,并且如何组合它们的问题并不简单.

一种方法可能看起来像这样.我会打电话给您正在放弃的回购source,以及您要保留的回购target.

首先,在每个存储状态下创建易于共享的引用source.

$ cd /path/to/source
$ git tag stash-s0 stash
$ git tag stash-s1 stash@{1} 
$ git tag stash-s2 stash@{2}
// etc.
Run Code Online (Sandbox Code Playgroud)

您还需要记下所有隐藏消息.他们在藏匿的reflog中.

$ git reflog stash
1111111 stash@{0}: Custom Stash Message Here
2222222 stash@{1}: WIP on master: 1234567 2
Run Code Online (Sandbox Code Playgroud)

(你可以将它们作为注释存储在标签上,但IMO真的不比其他任何东西更方便......)

现在您需要将这些标签(及其历史记录)复制到target; 这将确保存在所有存储的数据

$ cd /path/to/target
$ git fetch --tags file://localhost/path/to/source
Run Code Online (Sandbox Code Playgroud)

(file://localhost/path/to/source是一个可能的URL source,假设它可以在本地访问target;您可以使用任何git URL,或者如果source已经是已配置的远程URL,则target可以使用远程名称而不是url.)

现在是棘手的部分; 你需要重建stashreflog target.

首先,您需要跟踪targets stashreflog中已有的任何条目.您可以使用标签执行此操作,与存储条件相同source.

$ git tag stash-t0 stash
$ git tag stash-t1 stash@{1}
// etc.
Run Code Online (Sandbox Code Playgroud)

并且,再次记下现有的存储条目消息

$ git reflog stash
3333333 stash@{0}: WIP on master: 7654321 2
Run Code Online (Sandbox Code Playgroud)

然后你可以删除隐藏ref.通常情况下,我不会绕过git接口,但在这种情况下,它并不像是一种"安全"的方式.

$ rm .git/refs/stash
$ rm .git/logs/refs/stash
Run Code Online (Sandbox Code Playgroud)

最后,您可以构建新的存储堆栈.你的第一个命令是

$ git update-ref --create-reflog -m "<stash-message-1>" refs/stash <tag-name-1>
Run Code Online (Sandbox Code Playgroud)

或者,在新的足够版本的git上

$ git stash store -m "<stash-message-1>" <tag-name-1>
Run Code Online (Sandbox Code Playgroud)

你记录的存储信息在哪里<stash-message-1>,<tag-name-1>现在是堆栈中的最后一个(最旧/"底部")存储,以及你用来保存该存储状态的标记.每个后续命令都是

$ git update-ref -m "<stash-message-n>" refs/stash <tag-name-n>
Run Code Online (Sandbox Code Playgroud)

要么

$ git stash store -m "<stash-message-n>" <tag-name-n>
Run Code Online (Sandbox Code Playgroud)

在存储列表中"向前穿越".

然后你可以取消你使用的标签.

$ git tag -d stash-s1
// ...
Run Code Online (Sandbox Code Playgroud)

[1]在git中创建临时分支然后根据需要使用交互式rebase来清理历史记录是可行的,因为您最终准备将其迁移到"真正的"分支.而且无论如何,存储与真正的提交一样"重量级",因为存储真正的提交.藏匿是很好的,可以将一些变化推迟一分钟,这样你就可以快速地将你的工作树用于其他东西,但是长寿命的存储并不是最好的.