如何在Git中关闭一个分支而不从历史记录中删除它?

64
我想提交并关闭分支,但不从历史记录中删除它。使用Mercurial,我会使用commit --close-branch,然后update到之前的某个版本,并继续工作。但是使用Git...我感到困惑。

1
毋庸置疑,搜索这些关键词时,我大多数情况下找到的是相反的情况,即人们想要从历史中删除某些内容。 - o0'.
1
我觉得这让人困惑的是术语。在 Git 中,我认为你永远不会关闭一个分支。在 Mercurial 中,“close-branch” 到底是什么意思? - MikaelHalen
4
关闭Mercurial分支的一个很棒的效果是:没有人能够在该分支上继续进行推送。 - Git有类似的功能吗? - Robert Siemer
@RobertSiemer,这种功能不是开箱即用的,但应该有扩展或工具可以处理这种情况。 - o0'.
1
+Robert Siemer:你的观点是错误的。没有任何东西会阻止你将新的head推送到已关闭的分支上。如果已经有了不同的head,则需要合并或强制推送,但他们可以这样做。在Mercurial中,关闭分支唯一的作用就是设置一个标志,以便Mercurial可以默认从'hg branches'中隐藏该分支。在Git中,您可以删除本地分支并在远程保留历史记录。或者标记分支头并在所有地方删除该分支。你有几个选择。 - bambams
3个回答

86

在Git中,没有关闭分支的确切等效方式,因为Git分支比Mercurial更轻量级。它们在Mercurial中的等效方式更像是书签而不是分支。

如果我理解正确,在Mercurial中关闭一个分支大致相当于从分支列表中将其删除,因此您可以通过归档来实现相同的效果。一个常见做法是将其末尾标记为archive,并将其删除:

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

该分支将被删除,可以通过检出标签并重新创建分支来稍后检索:

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

至少在 git 1.9.1 中,我必须使用 git branch -D 而不是 -d - Tor Klingberg
1
如果相应的分支尚未完全与主分支合并,则需要使用-D。 - Simeon

3
我已经创建了一个PowerShell脚本来自动化这个过程。此脚本将存档3个月或更长时间的分支。您可以更改正则表达式(第11行)以匹配您的存档策略。
#Get all branches on remote and place in array. Format of strings in array is for example "3 months ago|origin/branch-name"
$branches = git branch -r --sort=-committerdate --format="%(committerdate:relative)|%(refname:short)|%(refname:lstrip=3)"
#Loop through all branches
ForEach ($branch in $branches)
{
  #split the branch between last commit time and branch name
  $split = $branch.Split("|")
  try
  { 
    #check if the last commit date is 4 months or more
    if($split[0] -match "((^([4-9]|10|11|12) month)|year)")
    {
      $splitBranch = $split[1].Split("/")
      #tag the branch
      git tag archive/$split[2] $split[1]
      #delete the branch
      git push --delete $splitBranch[0] $split[2]
      #add the archived branch name to a text file
      Add-Content .\archived.txt $split[1]
    }
  }
  catch
  {
    #log any branches that failed
    Add-Content .\archiveFailures.txt $split[1]
  }
}
#push all newly created tags
git push --tags

#to restore archived branch
#git checkout -b <branchname> archive/<branchname>

2

我的经验是Mercurial对关闭分支有很好的支持,举个例子。

Git也许希望你要么删除分支以保持可维护性,减少分支计数,要么坚持使用标签。只要你有一个标签,就可以将其恢复为分支。我使用别名命令和shell函数,使关闭分支变得容易(将其归档为标签以备后用,如果我再次找到它有用)。

我建议你只关闭你确定以后会有用的分支。当恢复分支并尝试合并时,需要进行大量的合并修复工作的可能性很高。但也可能只是想查看旧分支中代码的状态,在“删除”它但保留为标签的情况下保留它。

我在我的.gitconfig文件中使用这种方法,放在[alias]下面。

closebranch = "!w() { echo Attempting to close local and remote branch: $1 Processing...; echo Checking the branch $1 out..; git checkout $1; echo Trying to create a new tag archive/$1; git tag archive/\"$1\"; git push origin archive/\"$1\"; echo Deleting the local branch $1; git branch -d $1;  echo Deleting the remote branch $1; git push origin --delete $1; echo Done. To restore the closed branch later, enter: git checkout -b MyNewBranch archive/\"$1\"; }; w"

closebranchpassive = "!w() { echo Attempting to close local and remote branch: $1 Processing...; echo Checking the branch $1 out..; git checkout $1; echo Trying to create a new tag archive/$1; git tag archive/\"$1\"; git push origin archive/$1; echo Deleting the local branch $1;   echo Deleting the remote branch $1;  echo Done. To restore the closed branch later, enter: git checkout -b MyNewBranch archive/\"$1\"; }; w"

closeremotebranch =  "!w() { echo Attempting to close remote branch: $1 Processing...; echo Checking the branch $1 out..; git checkout $1;  echo Trying to create a new tag archive/$1; git tag archive/\"$1\"; git tag archive/\"$1\"; echo Deleting the remote branch $1; git push origin --delete $1; echo Done. To restore the closed branch later, enter: git checkout -b MyNewBranch archive/\"$1\"; }; w"

这里使用Git shell函数来使用更简单的语法删除Git分支。
您可以选择仅删除远程分支,或同时删除远程和本地分支,以“被动”或更强制的方式进行操作,如下所示。
旧的远程分支保留为具有前缀名称“archive/”​​​​​​的标记分支,因此例如Azure Devops或类似的Git客户端/(基于Web的)存储库浏览器将在列出分支时在文件夹结构中显示标记。
要使用它,您可以像这样关闭分支'feature/#123-somefeature-branch':
git closebranch feature/#123-somefeature-branch 

这将会:
  • 检出分支到本地仓库 - 警告 - 考虑在此处添加 git pull,以确保您的本地分支副本包含所有更新
  • 标记已检出的分支
  • 将标签推送为名为“archive/[branchname]”的标签
  • 删除远程分支
  • 删除本地分支

您最终将处于分离状态,在其中您将看到如何稍后恢复您的“关闭”分支,现在它作为远程标签存在,可以检出并恢复为分支,例如: git checkout -b feature/#123-somefeature-branch-restoredalive-again archive/feature/#123-somefeature-branch


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接