有时我想通过删除所有本地制作的分支来清理我的个人git仓库。但是,我喜欢在推动变革之前进行重组。凭借自身的变化:
git reflog
但是如果我删除了分支,我也会删除reflog(因此无法访问这些提交对象)。有没有办法删除分支,但保留reflog?
目前,我通过在我的机器上创建一个名为backup
的辅助仓库解决了这个问题,然后在重新定位和任何其他“破坏性”操作之前将其推送到那里。这样备份的reflog保留所有活动。但是如果可能的话,我宁愿将reflog保存在我的主仓库中。
答案 0 :(得分:2)
编辑:既然编辑了这个问题以澄清它,那么大部分答案都是无关紧要的。短版本是“不,至少还没有:删除分支时删除reflogs”。如果某些问题可以解决,有一些建议可以在未来的git版本中对此进行更改。 (我认为这样会很好,因为你可以做git branch --undelete foo
,或者他们决定拼写它,然后把所有东西都归还,全部从保存的reflog中恢复。最大的问题纯粹是一个实现细节:if你有一个分支x
并删除它然后创建一个分支x/sub
,删除分支的reflog将占用必须成为目录的名称x
。还有一个问题是什么它意味着创建分支x
,删除分支x
,并再次创建分支x
而不使用某种--undelete
拼写:这对旧{{1}做了什么reflog?)
起初我认为你的意思是“删除一个分支但保留其reflog”(答案当前为“no”,删除分支时reflogs会被删除,尽管有一些建议要改变这个,如果有些问题可以解决。但现在我认为你的意思是,你有这样的东西(x
的输出):
git log --oneline --graph --decorate
然后,您希望将您的本地* 9390606 (devel, origin/devel) latest tip
| * a45b0c4 (branch-X) some work, finished
| * a37b5ec some work, phase two
| * eef283e some work, phase one
|/
* 1f0507b starting point
重新命名为分支的提示,其名称为branch-X
和devel
,同时还保留原始分支origin/devel
,其他一些名字。
这很容易做到。复制分支标签,然后重新定义:
branch-X
让我们说在rebase中你将所有三个阶段结合起来并改变信息。这给你:
$ git checkout branch-X
$ git branch branch-X-v1
$ git rebase -i devel # with or without -i, really
您可能想要做的另一件事是“隐藏”标签* 3afbcac (branch-X) add feature X
* 9390606 (devel, origin/devel) latest tip
| * a45b0c4 (branch-X-v1) some work, finished
| * a37b5ec some work, phase two
| * eef283e some work, phase one
|/
* 1f0507b starting point
,而不是在普通视图中看到这些提交。有一种方法可以做到这一点,甚至更容易:不复制标签,只需进行rebase。
让我们暂停一下,然后描述一下git的标签机制。标签是人类可读的字符串,通过其丑陋的SHA-1(完整的SHA-1,而不仅仅是上面显示的7个字符的缩写)来标识提交(或其他git对象)。
git中的所有标签都非常相似:它们只是名称,主要位于类似顶级目录的名称branch-X-v1
下。分支和标签分别位于refs/
和refs/heads/
。 1 关于分支和标记名称还有一些其他“特殊”的东西:具体来说,各种git命令(如{{ 1}}和refs/tags/
)自动查找它们。分支更加特殊,因为git branch
将“on”一个,然后git知道在那里进行新的提交时自动推进分支引用,并在git tag
上移动标签,等等上。但是为了标记一系列提交的提示,例如三个git checkout
提交,任何名称都可以。你需要的是另一个名字。
幸运的是,有一些内置于git的名称可以持续“一段时间”,但不会显示在rebase
输出中。这些是git的“reflogs”,您可以使用some work
和git log --all
查看这些内容。您会看到git reflog
等名称,用于跟踪git reflog branch
之前branch-X@{1}
所指向的位置。
这里的缺点是这些名称是临时的 2 且相对(branch-X
变为rebase
,branch-X@{1}
变为branch-X@{2}
,依此类推,每次分支尖端移动)。您也可以使用像{2}
这样的表格,这可以提供帮助,但我希望自己的名字更加永久和稳定。
您可以使用非分支名称。显而易见的是标签。而不是将分支标签复制到另一个分支,如{3}
,而是将其复制到标记:
@{yesterday}
但你也可能会发现这些问题也很混乱。
如果您愿意,可以将其复制到标准名称空间之外的名称,但即使是那些也会显示在branch-X-v1
输出中,它会查看所有引用,而不仅仅是分支和标签。如果您的观看者 - 无论是您正在运行git tag tag-X-v1
,还是--all
或其他GUI使用git log
而不是gitk
,那么这些“外部名称”将被隐藏,以及他们标记的提交。但是你必须每次使用--branches --tags --remotes
或你放入它们的任何空间明确拼写它们;并且您必须使用--all
来创建和删除它们。 (你当然可以将它放在一个脚本中:事实上,refs/mine/
适用于脚本。)
我个人的偏好就是使用额外的分支名称。当我修改提交系列时,我结束了git update-ref
到git update-ref
或其他什么。
1 “远程分支”位于X-v1
。 Notes,有点像git的新东西,住在X-v5
。 refs/remotes/
命令使用refs/notes/
。我认为这是一个完整的清单,至少在今天,但很难确定。
2 默认情况下,它们会在30天后过期。有时它们默认持续90天,但不适用于这种特殊情况,因为无法从rebase后的分支尖端访问pre-rebase branch-tip。