How to close a branch WITHOUT removing it from history in git?

GitBranch

Git Problem Overview


I'd like to make a commit and close its branch, without removing it from history.

With mercurial I'd commit --close-branch, then update to a previous one, and go on working. With git... I'm confused.

Git Solutions


Solution 1 - Git

There's no exact equivalent to closing a branch in Git, because Git branches are more lightweight than in Mercurial. Their Mercurial equivalent is more bookmarks than branches.

If I understand correctly, closing a branch in Mercurial roughly makes it disappear from the branch list, so you can achieve the same thing by archiving it. A usual practice is to tag its tip as archive, and delete it:

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

The branch will be deleted, and can be retrieved later by checking out the tag, and recreating the branch:

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

Solution 2 - Git

I've created a powershell script to automate the process. This script archives branches 3months old or more. You can change the regex (line 11) to match your archive strategy.

#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>

Solution 3 - Git

My experience is that Mercurial has good support for closing branches, to give an example.

Git perhaps expects you to either delete branches to keep it maintainable in a way of reducing the branch count, or stick to tags. As long as you got a tag, you can restore it into a branch again. I use aliased commands with shell functions so I with ease can close a branch (archive it as a tag for later restoration, if I find use of it again).

I would suggest you only close branches you are sure will be useful later. Chances are high that you need to do a lot of merge fixing when restoring the branch and try to merge it in. But it can also be that you want to just see the state of the code in an old branch, where you 'delete it' but keep it around as a tag.

I use this approach inside my .gitconfig under [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"

This uses Git shell functions to use an easier syntax to delete a Git branch.
You can decide to either delete the remote branch only, or both the remote and local branch, either in a 'passive' or a more forced way as shown.

The old branch remotely is kept as a tag branch with the prefixed name 'archive/' so for example Azure Devops or similar Git clients / (web based) repo browsers will show the tag inside a folder structure when listing the branches.

To use it you can for example close the branch 'feature/#123-somefeature-branch' like this :

git closebranch feature/#123-somefeature-branch 

This will :

  • Check out the branch to local repo - warning - consider adding also a git pull here to be sure your local copy of the branch contains ALL updates
  • Tag the branch checked out
  • Push the tag as a tag named 'archive/[branchname]'
  • Delete the remote branch
  • Delete the local branch

Youll end up in a detacted state where you are greeted with how you can restore your 'closed' branch later on, which now exists as a remote tag, which can be checked out and restored to a branch i.e. git checkout -b feature/#123-somefeature-branch-restoredalive-again archive/feature/#123-somefeature-branch

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiono0&#39;.View Question on Stackoverflow
Solution 1 - GitCharlesBView Answer on Stackoverflow
Solution 2 - GitgarethbView Answer on Stackoverflow
Solution 3 - GitTore AurstadView Answer on Stackoverflow