Reputation: 7157
In svn, I would often delete branches which contained work I was no longer interested in, safe in the knowledge I could recover them at any future time if I ever really needed to.
In git, it seems this is impossible. This means I now have about 50 branches or so in 'git branch -a', which I do not expect to ever use again, but do not want to lose them forever.
Is there really no way in git of deleting a branch in a version controlled way? Without sounding anti-git, why is git designed so it is almost required (it seems to me) to throw away old branches in such a way they cannot be recovered? Doesn't this go against the idea of version control.
Upvotes: 3
Views: 430
Reputation: 60275
I just this morning realized the right answer to this:
everything under .git/refs is a reference and so won't be pruned, but only refs/heads are branches, refs/tags are tags, etc. So just shunt the branch off to an "archive" refs dir.
The really brute-force method is to just mkdir -p .git/refs/archive/heads; mv .git/refs{,/archive}/heads/master
which will stomp on any previously-archived version of that branch; here's a more thorough version:
#!/bin/sh
# archive a branch, by committing it to .git/refs/archive/heads/
# to unarchive the branch, say 'git branch mybranch archive/heads/mybranch~'
# ---- NOIICE the parent link in the branch command above ----------------/
# any second parent of the archive ref is the previous archive header commit
getopts x x && set -x -v && shift
while test $# -ne 0; do
branch="refs/heads/$1"
archive="refs/archive/heads/$1"
git rev-parse -q --verify "$branch" >&- \
|| { echo >&2 archive-branch ignored nonexistent branch: $1; shift; continue; }
previously=`git rev-parse -q --verify "$archive"`
git mktree </dev/null | xargs git commit-tree \
-p "`git rev-parse "$branch"`" \
${previously:+ -p $previously} \
-m "Parent is the archived tip of branch '$1'" \
${previously:+ -m 'Second parent is the previous commit like this one.'} \
> "`git rev-parse --git-dir`/$archive"
rm "`git rev-parse --git-dir`/$branch"
shift
done
Upvotes: 0
Reputation: 19475
You could create a ref to the branch head that is outside of the normal namespaces that git uses. This would prevent git branch
from listing the branch, but would ensure that the commits for that branch are not garbage collected and would still provide a name to get back that branch if you later decide that you actually want it.
git update-ref refs/attic/old_topic_branch old_topic_branch
git branch -D old_topic_branch
Branches in this attic space could be listed with:
git for-each-ref refs/attic
And a branch could be recovered with:
git checkout -b old_topic_branch refs/attic/old_topic_branch
But you would still need to be careful to move those refs to a new repository if you plan to abandon your old repository at any point (such as moving to a new computer), since these refs would not be copied over when cloning the repository.
Upvotes: 3
Reputation: 4766
One possibility is to create a tag for the branch you want to archive and then you can delete the branch.
git tag -a <tagname> <branchname>
Then, if you ever want to recover the branch you can create a new branch from the tag.
git checkout -b <branchname> <tagname>
It might also help to develop a naming scheme for the tags so that all of your archived branch tags are together and at the top or bottom of the tag list.
Upvotes: 3
Reputation: 62379
Another possibility is simply renaming "dead" branches, possibly in conjunction with "namespacing" them. For example, if I don't need the branch topicbranch42
anymore, but I might need it in the future for reference, just do this:
git checkout master # or any other branch that isn't topicbranch42
git branch -m topicbranch42 deprecated/topicbranch42
That way, you keep all the branches around, but their names provide a pretty clear indicator they're not in active development/use
Upvotes: 1
Reputation: 993085
One thing I do sometimes is to rename branches with a prefix:
git branch -m foo old/foo
Another thing you can do is push the branches you want to save to another bare Git repository for safekeeping, and then delete them in your local repo:
git remote add archive /path/to/archive/repo.git
git push archive foo
git branch -D foo
Upvotes: 3
Reputation: 887433
Deleting a git branch just deletes a label that refers to a commit.
You can run git checkout <commit-hash>
to recover the deleted branch, as long as you write down the hash somewhere.
Running git gc
will permanently delete these orphaned commits.
Upvotes: -1