是否可以将git存储推送到远程存储库?

And*_*imm 190 git git-stash

在git中,是否可以创建存储,将存储推送到远程存储库,在另一台计算机上检索存储,并应用存储?

或者是我的选择:

  • 创建补丁并将补丁复制到另一台计算机,或
  • 创建一个次要分支并将不完整的工作提交给该分支?

seh*_*ehe 71

注意:我刚刚用24小时更多的git-fu重写了这个答案:)在我的shell历史中,整个shebang现在是三个单行.但是,为了您的方便,我已经将它们解开了.

这样,我希望你能看到我是如何做的,而不是只是盲目地复制/粘贴东西.


这是一步一步的.

假设〜/ OLDREPO中的源包含stashes.创建一个不包含stashes的TEST克隆:

cd ~/OLDREPO
git clone . /tmp/TEST
Run Code Online (Sandbox Code Playgroud)

将所有存储器作为临时分支推送:

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

在接收端循环以转换回被收藏:

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
Run Code Online (Sandbox Code Playgroud)

如果愿意,清理你的临时分支机构

git branch -D $(git branch|cut -c3-|grep ^stash_)
Run Code Online (Sandbox Code Playgroud)

做一个git存储列表,你会这样:

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
Run Code Online (Sandbox Code Playgroud)

在原始存储库中,看起来像

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
Run Code Online (Sandbox Code Playgroud)

  • 这对我来说很有效,除了我在`git stash save ...`之前需要一个`git add .`,因为`git stash`拒绝存储新文件,除非它们已经上演.另外,将`git rev-list ...`到`tac`的结果换成了stashes的顺序,这样它们就会以相同的顺序出现. (9认同)
  • @sehe 优秀的剧本!!两个建议:1) --reverse the final ref-list,以便目标 repo 中的隐藏顺序与原始顺序相同。2) 使用 `git branch -D stash_$a` 结束最终的 `for` 循环(在创建 stash 时进行清理),这样如果出现问题并且我们重试,我们不会重新处理已经成功隐藏的提交。 (2认同)
  • 解决方案可以进一步改进:如果将 `git stash save "$(git log --format='%s' -1 HEAD@{1})"` 替换为 `git update-ref --create-reflog -m "$(git show -s --format=%B $rev)" refs/stash $rev` 你会得到原始的存储消息(`update-ref` 是幕后的 `git stash save` )。 (2认同)

u0b*_*6ae 61

它不可能通过fetch得到它,镜像refspec是fetch = +refs/*:refs/*,即使存储refs/stash它不会被发送.显式refs/stash:refs/stash也没有效果!

无论如何它只会令人困惑,因为那不会取得所有的藏匿处,只会取出最新的藏匿处; stashes列表是ref 的reflogrefs/stashes.

  • 您可以从git远程获取最新的存储,但不能从您的存储中获取,只能到另一个参考.像`git fetch some-remote + refs/stash:refs/remotes/some-remote/stash``git stash apply some-remote/stash`.但是你不能得到更老的藏匿处,因为它们存储在不可获取的reflog中.请参见http://stackoverflow.com/questions/2248680/can-i-fetch-a-stash-from-a-remote-repo-into-a-local-branch/29839687#answer-29839687 (3认同)

Vic*_*ian 31

我参加聚会的时间有点晚了,但我相信我发现了一些对我有用的东西,如果你的情况相同或类似,也可能适合你.

我正在自己的分支机构中开发一个功能.分支机构没有合并为主机,直到完成或我已经提交了我觉得很舒服的向公众展示.因此,当我想将非分段更改传输到另一台计算机时,我所做的是:

  • 使用像" [non-commit] FOR TRANSFER ONLY" 这样的提交消息进行提交,其中包含您要传输的内容.
  • 登录到另一台计算机.
  • 然后做:

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

    如果以不同方式访问存储库,则URL可能会有所不同.这会将该URL中的更改从远程分支"rb"拉入本地分支"lb".请注意,我在自己的计算机上运行了一个ssh服务器,并且能够以这种方式访问​​存储库.

  • git reset HEAD^(暗示--mixed)

    这会将HEAD重置为指向"[non-commit]"提交之前的状态.

从git-reset(1):" --mixed:重置索引但不重置工作树(即更改的文件被保留但未标记为提交)[...]"

因此,您最终将对文件进行更改,但不会对master进行提交,也不需要存储.

但是,这将要求您git reset --hard HEAD^在存储器中进行"[非提交]",因为该提交是垃圾.

  • 这比创建一个新的功能分支然后删除它要脏得多.... (2认同)

Sir*_*ert 20

这有点晚了,但这个答案可能对某人有所帮助.我想知道这一点,因为我希望能够在另一台计算机上推送正在进行的功能/错误/任何工作.

对我有用的是提交我正在进行的代码(在我正在单独工作的分支中).当我到达我的另一台计算机时,请执行pull,然后使用以下命令撤消提交:

git reset --soft HEAD^
Run Code Online (Sandbox Code Playgroud)

继续按原样工作,在那里进行所有正在进行的更改,未提交,并且未分级.

希望能帮助到你.


Dan*_*ski 16

似乎有一个非常巧妙的技巧来解决这个问题.您可以使用git diff > file.diff(并提交文件),然后使用git apply file.diff(从任何地方)恢复更改以获得相同的结果.

这也在这里解释.

  • 如果您有未跟踪的文件:1.git add.2. git diff HEAD> file.diff (4认同)

Sco*_*don 10

目前接受的答案是技术上是正确的,你不能直接通知Git所有的储物箱推到远程,然后拉成的一切另一台计算机上的本地藏匿。

虽然目前最高投票的答案应该有效,但我不喜欢它创建了一堆临时分支,并且它需要手动检查存储提交并将其保存为存储,这可能会导致类似此评论的问题提到,并导致重复On (no branch): On testing:。当然必须有更好的方法!

因此,虽然您不能直接推送 stash,但 stash 只是一次提交(实际上是两次提交),并且根据git push手册页您可以推送提交:

<src>往往是你想推分支的名字,但它可以是任意“SHA-1的表达” ...

我选择将 stashes 推到,refs/stashes/*这样我就不会用额外的树枝弄乱我的遥控器。所以我可以这样做:

git push origin stash@{0}:refs/stashes/$(git rev-parse --short stash@{0})
Run Code Online (Sandbox Code Playgroud)

(该rev-parse命令获取存储的短散列,这对于回购来说是唯一的。)

接下来,我需要从另一台计算机获取存储。Git 默认只获取分支,所以我需要专门获取 stashes:

git fetch origin refs/stashes/*:refs/stashes/*
Run Code Online (Sandbox Code Playgroud)

现在将存储提交转换回实际存储。如前所述,虽然我可以像往常一样检查存储提交、重置和存储,但我不喜欢它需要额外的步骤,或者它可能无法维护存储的索引状态。我在网上寻找一种自动执行此操作的方法,但我的搜索功能失败了。最后,我查看了 手册页git stash,在那里我找到了这个:

create
创建一个 stash(这是一个常规提交对象)并返回其对象名称,而不将其存储在 ref 命名空间中的任何位置。这旨在对脚本有用。它可能不是您要使用的命令;请参阅上面的“保存”。

store 将
通过 git stash create(这是一个悬空合并提交)创建的给定存储存储在存储引用中,更新存储引用日志。这旨在对脚本有用。它可能不是您要使用的命令;请参阅上面的“保存”。

由于我已经提交了,store听起来像我想要的。所以我可以这样做:

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

替换<SHA>为刚刚获取的 stash。

(该git show命令从存储提交中获取提交消息,用作存储日志的消息。)

存储现在在我的本地存储库中正常显示:

$ git stash list
stash@{0}: On master: temp
...
Run Code Online (Sandbox Code Playgroud)

要清理遥控器,可以像这样从遥控器中删除隐藏:

git push origin :refs/stashes/<SHA>
Run Code Online (Sandbox Code Playgroud)

这种方法还有一个好处是幂等:如果你push再次运行命令,它会报告Everything up-to-date. 该fetch命令也可以安全地重复运行。虽然stash store如果它与最近的存储相同,将跳过存储存储,但它不会阻止旧存储的重复。不过,这可以解决,就像我在我的git-rstash脚本中所做的那样,见下文。


为了完成,您还可以轻松推送所有存储(使用):

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
Run Code Online (Sandbox Code Playgroud)

或导入所有获取的隐藏:

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

我创建了一个可以作为子命令调用的脚本(例如git rstash push 0),所以我不必记住所有这些。 git-rstash可以在这里找到。


Eim*_*tas 9

我会采用第二种方法,但不知道为什么你不能将它提交给master/featured分支.也可以做樱桃采摘.

  • 没有技术理由不承诺掌握/特色,只是我想说"这不是一个真正的提交,它只是保存我的工作,所以我可以在另一台机器上得到它". (24认同)

arg*_*ith 6

AFAIK stash 的整个想法是在当地的地毯下隐藏一些不那么重要的东西。没有人应该知道你最喜欢的废话 ;-) 唯一的“但是”是:但是如果我在几个工作站上开发?然后scp就好多了。

  • 这种有趣的东西应该是评论。;-) (9认同)
  • 这里有 git-ssh-newbie,但是你可以在 github 上使用 scp 吗? (2认同)