如何归档git分支?


305

我的git存储库中有一些旧分支,这些分支不再处于活跃开发中。我想对分支进行存档,以便在运行时默认情况下不显示它们git branch -l -r。我不想删除它们,因为我想保留历史记录。我怎样才能做到这一点?

我知道可以在ref / heads之外创建一个ref。例如,refs/archive/old_branch。这样做有什么后果吗?


git-rm不会从资源库中删除资源,它只会从索引kernel.org/pub/software/scm/git/docs/git-rm.html中删除它们。您可以使用git checkout [rev] file
Dana Sane

1
从来没听说过。不过,我使用Attic/<branchname>轻量级标签来归档分支。
2009年

标签是快速,安全和理智的选择。
kch

Answers:


401

我相信执行此操作的正确方法是标记分支。如果您在标记了分支之后删除了该分支,则可以有效地保留该分支,但不会使分支列表混乱。

如果您需要返回分支,只需签出标签即可。它将有效地从标签恢复分支。

要归档和删除分支:

git tag archive/<branchname> <branchname>
git branch -d <branchname>

要在以后恢复分支:

git checkout -b <branchname> archive/<branchname>

分支的历史记录将与标记时的历史记录完全一样。


11
我是Git新手,但是尝试此操作时,我认为恢复分支的正确命令是:git checkout -b <branchname> archive/<branchname>
Steve 2010年

6
在这种情况下,是否有任何理由不使用对象标签?能够看到谁归档了分支以及何时归档。
格雷戈里·约瑟夫

7
@GrégoryJoseph:这就是所谓的“带注释的标签”。是的,我会说,使用它可能很有意义。
onnodb 2013年

22
小注释,您可能想要,branch -D因为如果以这种方式进行归档,则可能无法完全合并
Arkadiy Kukarkin 2014年

5
非常好。是带有说明的完整教程。
Guyaloni'2

123

杰里米的回答原则上是正确的,但是恕我直言,他指定的命令不太正确。

以下是将分支归档到标签而无需检出分支的方法(因此,在删除该分支之前不必检出另一个分支):

> git tag archive/<branchname> <branchname>
> git branch -D <branchname>

这是还原分支的方法:

> git checkout -b <branchname> archive/<branchname>

18
我想您还没有足够的分数,但是当您只编辑现有答案时还是会更好-+1仍然可以:)
jkp 2011年

5
@jkp通常不赞成编辑其他用户的代码和命令,因为git命令中的细微更改可能会导致截然不同的事情,并且您可能不明白为什么原始作者以他们的方式编写内容。最好自己做出答案或发表评论。
丹·贝查德

甚至比完全不同的事情更糟,命令或代码的细微更改可能导致微妙的结果,这可能很难弄清楚,我建议您留下评论,以便答案的发布者可以编辑自己或做出回应提出反诉的结果可能会有所不同(这种反诉比较普遍)
Nicholas Pipitone

22

是的,您可以使用创建带有一些非标准前缀的引用git update-ref。例如

  • 存档分支: git update-ref refs/archive/old-topic topic && git branch -D topic
  • 恢复分支(如果需要): git branch topic refs/archive/old-topic

带有非标准前缀(此处refs/archive)的引用不会出现在通常的上git branchgit log也不会出现git tag。不过,您可以使用列出它们git for-each-ref

我正在使用以下别名:

[alias]
    add-archive = "!git update-ref refs/archive/$(date '+%Y%m%d-%s')"
    list-archive = for-each-ref --sort=-authordate --format='%(refname) %(objectname:short) %(contents:subject)' refs/archive/
    rem = !git add-archive
    lsrem = !git list-archive

另外,您可能需要配置遥控器,例如push = +refs/archive/*:refs/archive/*自动推送存档的分支(或git push origin refs/archive/*:refs/archive/*单次推送)。

另一种方法是在删除分支之前在某个位置记下SHA1,但这有其局限性。没有任何参考的提交将在3个月后(或几周没有reflog)进行GC处理,更不用说手动了git gc --prune。由refs指向的提交对于GC是安全的。

编辑:通过@ap找到相同想法的perl实现:git-attic

编辑^ 2:找到一个博客帖子,其中Gitster自己使用相同的技术。


3
太好了,除了这个线程上的其他所有人之外,您实际上回答了这个问题。
tzrlk

20

扩展了史蒂夫的答案以反映遥控器上的更改,我做到了

 git tag archive/<branchname> <branchname>
 git branch -D <branchname>
 git branch -d -r origin/<branchname>
 git push --tags
 git push origin :<branchname>

要从远程还原,请参阅此问题


18

您可以将分支存档在另一个存储库中。不太优雅,但我想说这是一个可行的选择。

git push git://yourthing.com/myproject-archive-branches.git yourbranch
git branch -d yourbranch

4
您可以创建git-bundle而不是单独的存储库。
2009年

9

这是一个别名:

arc    = "! f() { git tag archive/$1 $1 && git branch -D $1;}; f"

像这样添加它:

git config --global alias.arc '! f() { git tag archive/$1 $1 && git branch -D $1;}; f'

请记住,git archive已经有命令,因此您不能将其archive用作别名。

您还可以定义别名以查看“已存档”分支的列表:

arcl   = "! f() { git tag | grep '^archive/';}; f"

关于添加别名


3
使用Git的较新版本(如建议在这里),这个别名给完成:!git tag archive/$1 $1 && git branch -D
缺乏

5

我正在使用以下别名来隐藏已归档的分支:

[alias]
    br = branch --no-merge master # show only branches not merged into master
    bra = branch                  # show all branches

因此,git br要显示积极发展的分支,并git bra显示所有分支,包括“已归档”分支。


5
分支是否已合并到master与其存档状态无关。例如,在我的开发团队中,我们有几个专门用于测试内容的分支。我们希望将这些分支保留在存档中,但是我们绝对不希望将它们合并到master中。
巴特

4

我不会存档分支。换句话说,分支机构将自己存档。您想要的是确保可以通过可靠的方式找到与考古学家有关的信息。可靠的是,它们有助于日常开发,并且不会在完成工作的过程中增加额外的步骤。也就是说,我不相信人们在完成分支后会记得添加标签。

这两个简单的步骤将极大地帮助考古开发。

  1. 使用简单的命名约定将每个任务分支与问题跟踪器中的关联问题链接
  2. 始终用于git merge --no-ff合并任务分支;您想要合并提交和历史记录气泡,即使只是一次提交。

而已。为什么?因为作为代码考古学家,我很少要开始了解分支上的工作。远东更多的时候它就是为什么在所有的尖叫九层地狱的代码写成这样?我需要更改代码,但是它具有一些奇怪的功能,并且我需要使它们困惑以免破坏重要的东西。

下一步是git blame找到关联的提交,然后希望日志消息可以解释。如果需要更深入地研究,我将找出工作是否在分支中完成,并整体阅读分支(以及问题跟踪器中的注释)。

比方说git blame提交XYZ。我打开一个Git历史记录浏览器(gitk,GitX git log --decorate --graph等),找到XYZ提交并查看...

AA - BB - CC - DD - EE - FF - GG - II ...
     \                       /
      QQ - UU - XYZ - JJ - MM

有我的分店!我知道QQ,UU,XYZ,JJ和MM都是同一个分支的一部分,我应该查看它们的日志消息以了解详细信息。我知道GG将是合并提交,并具有希望与跟踪器中的问题相关联的分支的名称。

如果由于某种原因,我想找到一个旧的分支,可以运行git log并在合并提交中搜索分支名称。即使在非常大的存储库上,它也足够快。

这就是我说分支机构自己存档时的意思。

标记每个分支会增加不必要的工作来完成工作(这个关键过程应该无情地简化),用数百个仅偶尔有用的标记来标记列表(不是说性能,而是人类可读性),并且是“在考古学中甚至非常有用。


2
但是,混乱如何?也许有办法将旧树枝隐藏在10立方码的尘土下。
bvj

1
这很有用,但不适用于未合并的分支。有时,在分支上进行了一项实验,您希望保留其中的内容,以防某些内容以后变得有用。
尼尔·梅休

1
@bvj我认为这个答案建议您应该始终删除合并的分支,因为您始终可以通过合并提交返回到它们。我同意这一点。
尼尔·梅

@NeilMayhew是的,我大约有10个这样的未合并分支机构。每个都与一个开放的任务相关联,因此我可以记住我当时在做什么。我要么对他们做点什么,要么它们变得过时了,它们不再相关,我将其删除。我从事的项目绝对淹没在“以后可能需要”分支中,所以我们几乎看不到我们在做什么。对于某些开发人员而言,不必自己清理自己确实是一个借口。留出一点余地是可以的,但是不要让它失去控制。
Schwern

@Schwern,我同意。我也参与过类似的项目。我认为将分支转换为标签是摆脱混乱的好方法,因为标签列表总是会增长,而分支列表却不会(因为它代表正在进行的工作量)。对标签使用命名空间可以使列表更易于管理,但是绝对必须抵制packrat的趋势。开发人员应该将提交保留在自己的计算机上,除非很有可能其他人最终会使用它们。
尼尔·梅休

2

我的方法是使用“ trash_”前缀重命名所有我不在乎的分支,然后使用:

git branch | grep -v trash

(带有外壳键绑定)

要保留活动分支的颜色,需要:

git branch --color=always | grep --color=never --invert-match trash

2
如果重命名分支,则最好将它们放在命名空间“ archive /”中
qneill

1

您可以使用脚本来为您存档分支

大分支

它使用前缀archive /为您创建一个标签,然后删除该分支。但是在使用之前请检查代码。


用法- $/your/location/of/script/archbranch [branchname] [defaultbranch]

如果要运行脚本而不写位置,则将其添加到路径中

那你可以打电话给

$ archbranch [branchname] [defaultbranch]

[defaultbranch]是,它会去当归档完成分支。颜色编码存在一些问题,但其他问题应该起作用。我已经在项目中使用了很长时间,但是它仍在开发中。


1
每堆栈溢出帮助,您需要披露您与产品的隶属关系。
LittleBobbyTables-Au Revoir

哦,对不起,不知道。我是脚本的作者。
Banezaka 2014年

0

我有时将分支归档如下:

  1. 生成补丁文件,例如,format-patch <branchName> <firstHash>^..<lastHash>(使用来获取firstHash和lastHash git log <branchName>
  2. 将生成的补丁文件移动到文件服务器上的目录中。
  3. 删除分支,例如 git branch -D <branchName>

当您需要再次使用分支时,“应用”补丁。但是,git am根据目标分支的状态,应用补丁文件(请参阅参考资料)可能会很困难。从好的方面来说,这种方法的好处是可以对分支的提交进行垃圾收集,并在您的存储库中节省空间。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.