For how long can you restore/recover a deleted branch on GitHub?

Note that some pull-request pages on GitHub will not show the Delete/Restore branch buttons, even though the references are safely stored as described by Cupcake.

This probably means the same branch was used again in a later pull request. Search the repo (in GitHub) for the branch name and check the latest pull request on that branch. You should find the UI to restore (or delete) the branch there.


GitHub support would have a definitive answer, but I suspect it is based on the default 90 days period before automatic purge of the reflog.

gc.<pattern>.reflogexpire

git reflog expire removes reflog entries older than this time; defaults to 90 days.
With "<pattern>" (e.g. "refs/stash") in the middle the setting applies only to the refs that match the <pattern>.

But... I you had a local copy with that branch still declared in it... nothing would prevent you to push said branch back to the gitHub repo ;)

Cupcake's answer (upvoted) give that support answer: no limit, which means those two settings are both set to never:

  • gc.reflogexpire
  • gc.reflogexpireunreachable

That makes sense for a hosting repo service which doesn't modify those repos locally, and only store modifications pushed from external contributors.


Update Git 2.22 (Q2 2019, five years later): that last case (setting gc.reflogexpire and gc.reflogexpireunreachable to never) is better handled.

See commit bf3d70f, commit 978f430 (28 Mar 2019), commit fe66776, commit a65bf78, commit cd8eb3a, commit e5cdbd5 (15 Mar 2019), and commit 8bf1444 (13 Mar 2019) by Ævar Arnfjörð Bjarmason (avar).
(Merged by Junio C Hamano -- gitster -- in commit f3c19f8, 25 Apr 2019)

gc: handle & check gc.reflogExpire config

Don't redundantly run "git reflog expire --all" when gc.reflogExpire and gc.reflogExpireUnreachable are set to "never", and die immediately if those configuration valuer are bad.

As an earlier "assert lack of early exit" change to the tests for "git reflog expire" shows, an early check of gc.reflogExpire{Unreachable,} isn't wanted in general for "git reflog expire", but it makes sense for "gc" because:

  1. Similarly to 8ab5aa4 ("parseopt: handle malformed --expire arguments more nicely", 2018-04-21, Git v2.18.0-rc0) we'll now die early if the config variables are set to invalid values.
    We run "pack-refs" before "reflog expire", which can take a while, only to then die on an invalid gc.reflogExpire{Unreachable,} configuration.

  2. Not invoking the command at all means it won't show up in track output, which makes what's going on more obvious when the two are set to "never".

  3. As a later change documents we lock the refs when looping over the refs to expire, even in cases where we end up doing nothing due to this config.


I asked GitHub Support, this was their response (emphasis mine):

We use a separate ref namespace for all Pull Requests which we use for various things including restoring the branch. Since we keep those [Pull Request] refs indefinitely, there's no time limit on restoring a branch.

You can see these special references in your remote by using the following:

$ git ls-remote | grep pull
From [email protected]:<username>/<remote>.git
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa        refs/pull/1/head
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb        refs/pull/1/merge
cccccccccccccccccccccccccccccccccccccccc        refs/pull/2/head
dddddddddddddddddddddddddddddddddddddddd        refs/pull/2/merge

The references are namespaced under refs/pull/<pull request number>/. The head reference points at the tip of the branch that's being pull requested, i.e. the last commit on the branch. I'm not sure what the merge reference is though.

Tags:

Git

Github