我如何归档git分支?

dan*_*ges 280 git

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

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

Jer*_*all 366

我相信这样做的正确方法是标记分支.如果您在标记它之后删除了分支,那么您已经有效地保留了分支,但它不会使分支列表混乱.

如果您需要返回分支机构,请查看标签.它将有效地从标签恢复分支.

要归档和删除分支:

git tag archive/<branchname> <branchname>
git branch -d <branchname>
Run Code Online (Sandbox Code Playgroud)

一段时间后恢复分支:

git checkout -b <branchname> archive/<branchname>
Run Code Online (Sandbox Code Playgroud)

分支的历史记录将完全保留,就像标记它一样.

  • 小记,你可能想要`branch -D`,因为如果你以这种方式存档它可能不会完全合并 (20认同)
  • 缺少 2 个重要命令:“git push --tags”(新创建的存档标签推送到服务器)。`git push origin :&lt;branchname&gt;`(从服务器删除 &lt;branchname&gt;)。 (16认同)
  • 我是一个Git新手,但在尝试这个时,我认为恢复分支的正确命令是:`git checkout -b <branchname> archive/<branchname>` (11认同)
  • @GrégoryJoseph:这是一个所谓的"注释标签".是的,我会说,使用它可以很有意义. (7认同)
  • 在这种情况下,有没有理由不使用对象标签?能够看到谁归档了分支,什么时候可能很有趣. (6认同)
  • 非常好.[here](http://www.aaronwest.net/blog/index.cfm/2011/6/7/Git-Workflows-Archiving-Old-Branches)是一个包含解释的完整教程. (5认同)
  • 如果我要标记和存档的分支是远程的,这是否有效?我需要采取额外的步骤吗? (2认同)
  • 更一般,更有意义 imho `git tag [-a -m "some description possible"] archive/&lt;any_name_you_like&gt; &lt;branchname or commit&gt;`。当我在一个分支工作时,我做了这个,并决定我必须参加另一门课程。我继续在同一个分支上,但有重大变化。我所做的工作现在存储在具有良好名称和描述的存档标签中。 (2认同)

Ste*_*eve 117

Jeremy的答案原则上是正确的,但恕我直言他指定的命令并不完全正确.

以下是如何将分支归档到标记而无需签出分支(因此,在删除该分支之前,无需签出到另一个分支):

> git tag archive/<branchname> <branchname>
> git branch -D <branchname>
Run Code Online (Sandbox Code Playgroud)

以下是恢复分支的方法:

> git checkout -b <branchname> archive/<branchname>
Run Code Online (Sandbox Code Playgroud)

  • 我猜你还没有足够的分数,但是当你只是编辑现有的答案时会更好 - 尽管如此:) (17认同)
  • @jkp通常不赞成编辑其他用户的代码和命令,因为git命令中的细微更改可能会导致完全不同的事情,并且您可能不明白为什么原始作者以他们的方式编写内容。最好只是自己回答或发表评论。 (3认同)

sni*_*nip 21

是的,您可以使用一些非标准前缀创建一个引用git update-ref.(例如git update-ref refs/archive/old-topic your-commit)

与普通的分支或标签不同,这些引用不会在通常情况下显示git branch,git log也不会git tag(虽然您可以看到它们git log --all).

创建一个ref比仅复制SHA1有一些优势.SHA1在短期内已经足够了,但是没有任何参考的提交将在3个月后(或者没有reflog的几周)进行GC测试,更不用说手动了git for-each-ref.使用refs的提交对GC来说是安全的.

我正在使用以下别名:

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

此外,您可能希望配置遥控器,例如git gc --prune自动推送(或push = +refs/archive/*:refs/archive/*一次性推送).

编辑:通过@ap找到同一个想法的perl实现:git push origin refs/archive/*:refs/archive/*

编辑^ 2:找到一篇博客文章,其中Gitster自己使用相同的技术.

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

Aug*_*aas 18

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

git push git://yourthing.com/myproject-archive-branches.git yourbranch
git branch -d yourbranch
Run Code Online (Sandbox Code Playgroud)

  • 您可以创建`git-bundle`而不是单独的存储库. (4认同)

Lia*_*iam 14

我做了,扩展史蒂夫的答案以反映遥控器上的变化

 git tag archive/<branchname> <branchname>
 git branch -D <branchname>
 git branch -d -r origin/<branchname>
 git push --tags
 git push origin :<branchname>
Run Code Online (Sandbox Code Playgroud)

要从远程恢复,请参阅此问题.

  • 对于 Git v1.7.0+,最后一行也可以是 `git push origin --delete &lt;branchname&gt;`。来源:https://git-scm.com/book/en/v2/Git-Internals-The-Refspec (2认同)
  • 如果对命令进行一些解释,这个答案会更好。乍一看,他们似乎删除了远程分支两次。我怀疑这是真的,但我必须研究每个命令才能知道。 (2认同)

Ale*_*xey 9

这是别名:

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

像这样添加:

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

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

您还可以定义别名以查看"已归档"分支的列表:

arcl   = "! f() { git tag | grep '^archive/';}; f"
Run Code Online (Sandbox Code Playgroud)

关于添加别名

  • 使用较新版本的git(如[here](/sf/answers/527400261/)所示),此别名可以完成:`!git tag archive/$ 1 $ 1 && git branch -D` (3认同)
  • 对于好奇的人来说,根据我花了 5 秒浏览的文档页面,“git archive”用于创建 .tar 档案。 (2认同)

小智 5

我使用以下别名来隐藏存档的分支:

[alias]
    br = branch --no-merge master # show only branches not merged into master
    bra = branch                  # show all branches
Run Code Online (Sandbox Code Playgroud)

因此,git br要显示积极发展的分支机构,并git bra显示所有分支,包括"存档"分支.

  • 分支是否已合并为主分支与其归档状态无关.例如,在我的开发团队中,我们有一些专门用于测试内容的分支.我们希望将这些分支保留在我们的存档中,但我们绝对不希望将它们合并到master中. (3认同)

Sch*_*ern 5

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

这里有两个简单的步骤,它们将极大地帮助考古学发展。

  1. 使用简单的命名约定将每个任务分支与问题跟踪器中的相关问题联系起来
  2. 总是git merge --no-ff用来合并任务分支;你想要合并提交和历史泡沫,即使只有一次提交。

就是这样。为什么?因为作为代码考古学家,我很少从想知道分支上做了什么工作开始。更常见的是,为什么在所有尖叫的九个地狱中,代码都是这样编写的?!我需要更改代码,但它有一些奇怪的功能,我需要把它们弄明白以避免破坏一些重要的东西。

下一步是git blame找到相关的提交,然后希望日志消息是解释性的。如果我需要更深入地挖掘,我会找出工作是否在一个分支中完成并阅读整个分支(以及它在问题跟踪器中的评论)。

让我们说git blame提交 XYZ的点数。我打开一个 Git 历史浏览器(gitk、GitX git log --decorate --graph、等等...),找到 commit XYZ 并查看...

AA - BB - CC - DD - EE - FF - GG - II ...
     \                       /
      QQ - UU - XYZ - JJ - MM
Run Code Online (Sandbox Code Playgroud)

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

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

这就是我所说的分支归档本身的意思。

标记每个分支为完成工作增加了不必要的工作(一个应该无情地简化的关键过程),用数百个标签填充标签列表(不是说性能,而是人类可读性),这些标签只是偶尔有用,而且不是甚至对考古学非常有用。

  • 这很有用,但不适用于未合并的分支。有时,在一个分支上进行了一个实验,您希望保留这些内容,以防其中一些内容在以后变得有用。 (4认同)
  • 但是杂乱怎么办?也许如果有办法将旧树枝隐藏在 10 立方码的泥土下。 (3认同)
  • @bvj 我认为这个答案建议您始终删除合并的分支,因为您始终可以通过合并提交返回它们。我同意这一点。 (2认同)