Search code examples
gitgithubgit-push

How to split refs into chunks that are pushed accross several commands?


Let’s say I have a repository with a large number of releases (tags). The repository is valid and git fsck report nothing. But when I pushed the repository over ssh, I ended up withremote: Internal Server Error.

After investigating, it seems this the large number of refs which is the issue. I tried tried to set a repo with 4100 branches and the message was more verbose (manyfailed to lock).

Step to reproduce : push a repository with more than 5000 refs to a new empty repository on GitHub or GitHub enterprise. Or just fork this repo.

Is there a way to solve this without having to split the repo for pushing it in several parts ?


Solution

  • I ran into the same problem when trying to push a repo that had about 50,000 refs. Github support indicated that my only option would be to push a smaller chunk of refs at once.

    Here's the commandline I used (if you refs are located under a different namespace, i.e. refs/replace, use that instead of refs/heads).

    git for-each-ref --format="%(refname)" --sort='authordate' refs/heads | xargs git push origin
    

    Shells have a limit on how large a commandline string can be and xargs will intelligently split up the commands to stay under that limit. I found that Github was able to handle the amount that xargs was pushing at once but YMMV. If you're still hitting the Github limit, use the max-args option (some trial and error may be necessary).

    git for-each-ref --format="%(refname)" --sort='authordate' refs/heads | xargs --max-args=<1000> git push origin