【发布时间】:2019-05-30 21:36:44
【问题描述】:
我的stash 堆栈是否被推送到remote repo?还是完全无视?
我只是好奇我是否应该每隔一段时间就删除一些它以节省服务器上的空间。
【问题讨论】:
我的stash 堆栈是否被推送到remote repo?还是完全无视?
我只是好奇我是否应该每隔一段时间就删除一些它以节省服务器上的空间。
【问题讨论】:
没有。藏匿处是本地的。
$ man git stash:
当您想记录工作目录和索引的当前状态,但又想回到干净的工作目录时,请使用 git stash。该命令会保存您的本地修改,并恢复工作目录以匹配 HEAD 提交。
不过,我不会在本地保留太多它们。随着时间的推移,你会失去对它们的追踪,它们会变得有些无用。
【讨论】:
一般来说,不会。不过,如果您愿意,可以推动它。
这是关于推送(以及,就此而言,获取)的事情:这些工作基于“refspecs”,您可以在其中命名本地引用名称 - 或者,对于推送和特定情况,原始提交 ID - 然后也是一个远程引用名称。
大多数时候,您命名一个分支引用,例如master,或一个“远程分支”,例如origin/master。令人困惑的是,git 所说的“远程分支”实际上是一个本地实体,而不是 on 远程分支,而是 your 存储库中的一个特殊名称的分支。 p>
分支实际上只是一个名称以refs/heads/ 开头的引用。这几乎就是一个分支的全部内容。 (关于分支还有一个特别之处:当您在其中进行新提交时,分支会自动移动。也就是说,如果您在 master 分支上并且您进行了新提交,那么 git 会更新refs/heads/master 指向新的提交。)
“远程分支”只是一个引用,其名称以refs/remotes/ 开头,然后包含远程的名称(通常为origin)。所以refs/remotes/origin/master 是一个“远程分支”:一个本地实体,一个在 your repo 中的名称,您的 git 使用它来跟踪“上次 git 检查时 master 在 origin 上的位置与origin"。每当您从/向origin 获取或推送时,1 git 会根据它在“那边”看到的内容更新您的 origin/<em>branch</em> 名称。
标签只是以refs/tags/ 开头的引用。
通常你会忽略所有这些前缀,只写master 表示你的主分支,refs/heads/master,origin/master 表示refs/remotes/origin/master,v2.3 表示refs/tags/v2.3。 Git 会自动找出哪一个,因为这很明显。精确的规则在gitrevisions 中描述。 (令人讨厌的是,git checkout 和 git branch 并不总是完全遵循 gitrevisions 规则:当他们知道某些东西是分支名称时,他们只是假设 refs/heads/ 部分。其他 git 命令确实按照描述的方式工作。)
stash 脚本使用简单拼写为refs/stash 的引用。所以你可以通过写stash来命名这个引用; git会发现它不是一个分支,也不是一个远程分支,也不是一个标签,最后会求助于refs/stash来解析名字。2
这意味着如果你写:
$ git push origin stash:ssss
git 会找到你的存储(只有一个存储)并尝试将其推送到名为ssss 的远程引用。这很可能会失败;这是我尝试时发生的情况:
error: unable to push to unqualified destination: ssss
The destination refspec neither matches an existing ref on the remote nor
begins with refs/, and we are unable to guess a prefix based on the source ref.
error: failed to push some refs to 'ssh://[redacted]/tmp/t'
只是为了好玩,我尝试了下一个命令,得到了另一个错误:
$ git push origin stash:refs/ssss
Counting objects: 8, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 485 bytes | 0 bytes/s, done.
Total 4 (delta 3), reused 0 (delta 0)
remote: error: refusing to create funny ref 'refs/ssss' remotely
To ssh://[redacted]/tmp/t
! [remote rejected] stash -> refs/ssss (funny refname)
error: failed to push some refs to 'ssh://[redacted]/tmp/t'
但是,这行得通:
$ git push origin stash:refs/heads/ssss
这一次,它在远程创建了一个新分支,命名为ssss。它也可以推送到远程标签 (refs/tags/<em>tagname</em>)。
存储作为分支或标签没有多大意义,但您可以将其推送为一个。所有远程都知道,一旦你尝试这个,你正在发送一些提交对象及其关联的树、blob 等,并且它应该将“最尖端”提交存储在(完整)名称下您提供。3 这就是为什么您可以推送原始提交 ID,例如,在远程创建标签:
$ git push af7ec93:refs/tags/foo
(当然假设有一个 ID 以 af7ec93 开头的提交)。
“堆栈”是通过使用 refs/stash 引用的 reflog 生成的。当您编写stash@{1} 时,它使用相同的gitrevisions 规则来解析提交ID。由于git push 允许您使用任何解析为有效ID 的内容,您也可以将它们推送到远程名称。但你可能不应该;就像refs/stash 下最顶层的存储项一样,这些作为常规提交没有多大意义。 (Stash 在内部存储为合并提交,但它们的内容被奇怪地打包,尝试将它们用作普通提交会产生不太有用的结果。)
1从 1.8.2 左右开始,这在 git 中确实如此;但旧版本的 git 在获取时有时会跳过更新远程分支,特别是当 git fetch 被 git pull 调用时。
2如果你咨询gitrevisions,你会发现这也不是很准确:它会发现stash 和refs/stash 一样在寻找之前一个分支名称。
3git push 通常会自动构建全名:如果你推送你的master,即refs/heads/master,它知道这是一个分支,所以git push master:newbranch 创建refs/heads/newbranch 在遥控器上。但是,您可以拼出一个全名,以便在遥控器上创建一个标签,例如。这也适用于删除操作,例如,当您推送一个空的本地引用以删除远程引用时:git push :refs/tags/delete_me。
作为bcmcfc already said,保留一大堆藏匿处往往是个坏主意。相反,我要做的是保留一大堆树枝(除非我真的想将它们保存在某些遥控器上,否则我会避免推动它们);这些都有名字,因此更易于管理(但只有一点)。效率没有区别,因为 stash 和分支都只是用于包含提交——特殊的 stash 合并提交或普通提交。但是,如果您使用分支而不是存储,您可能需要确保将您的 push.default 配置为避免推送所有分支。
【讨论】: