HomePhabricator

Manually prune Git working copy refs instead of using "--prune", to improve…

Description

Manually prune Git working copy refs instead of using "--prune", to improve "Fetch Refs" behavior

Summary:
Ref T13448. When "Fetch Refs" is configured:

  • We switch to a narrow mode when running "ls-remote" against the local working copy. This excludes surplus refs, so we'll incorrectly detect that the local and remote working copies are identical in cases where the local working copy really has surplus refs.
  • We rely on "--prune" to remove surplus local refs, but it only prunes refs matching the refspecs we pass "git fetch". Since these refspecs are very narrow under "Fetch Only", the pruning behavior is also very narrow.

Instead:

  • When listing local refs, always list everything. If we have too much stuff locally, we want to get rid of it.
  • When we identify surplus local refs, explicitly delete them instead of relying on "--prune". We can just do this in all cases so we don't have separate "--prune" and "manual" cases.

Test Plan:

  • Created a new repository, observed from a GitHub repository, with many tags/refs/branches. Pulled it.
  • Observed lots of refs in git for-each-ref.
  • Changed "Fetch Refs" to "refs/heads/master".
  • Ran bin/repository pull X --trace --verbose.

On deciding to do something:

  • Before: since "master" did not change, the pull declined to act.
  • After: the pull detected surplus refs and deleted them. Since the states then matched, it declined further action.

On pruning:

  • Before: if the pull was forced to act, it ran "fetch --prune" with a narrow refspec, which did not prune the working copy.
  • After: saw working copy pruned explicitly with "update-ref -d" commands.

Also, set "Fetch Refs" back to the default (empty) and pulled, saw everything pull.

Maniphest Tasks: T13448

Differential Revision: https://secure.phabricator.com/D20892