Page History

Freaky Git stuff

Nigel Stanger edited this page on 14 Nov

Clone this wiki locally

LFS

Migrate a large repository to LFS in GitBucket

  1. Create a new repository newrepo on the server by cloning the old one.
  2. Clone newrepo to local.
  3. Initialise git-lfs in newrepo as per the git-lfs tutorial:
    git lfs track "*.thing1" "*.thing2"
    git add .gitattributes
    git commit -m "Track thing1, thing2 files (LFS)"
    git rm --cached "*.thing1" "*.thing2"
    git add .
    git commit -m "Convert last commit to LFS"
  4. Migrate the history as per the git-lfs tutorial:
    git lfs migrate import --everything --include="*.thing1,*.thing2"
    If you specify multiple --include switches only the last one will take effect, so to migrate multiple file types, put the glob expressions inside the same string as shown above.
  5. We now need to force push newrepo to remote, but it may be too large for nginx’s request size limits. If you happen to have release tags handily scattered throughout history (or you can identify some well-spaced commit hashes) you can reduce the request size by only pushing up to a certain commit, e.g.:
    git push --force origin 9d42ad26508d94429ce2179358db5c2bfc1dc03d:master
    # ...etc...
    # one last push to catch everything since the last tag:
    git push --force
    Do this for each of the tags/commits in chronological order. You can find the commit hashes for the tags using git show-ref --tags.
  6. Also force push the rewritten tags to prevent push/pull errors due to the different commit hashes:
    git push --force --tags
  7. Clean up local as per the git-lfs tutorial:
    git reflog expire --expire-unreachable=now --all
    git gc --prune=now

Migrate LFS repo to a different remote

Normally you just clone the old remote, create the new remote on GitBucket, then git push -u origin master (and maybe git push --tags). However this isn’t aware of LFS files, so it will only push the pointers and all your LFS files will be missing on the remote. The correct procedure:

  1. git clone <old remote>
  2. git lfs fetch --all in the local clone to make sure the clone has all of the LFS objects (including historical versions). If you don’t do this the LFS push later on may fail due to missing objects.
  3. git remote set-url <new remote> in the local clone.
  4. git push -u origin master as usual in the local clone to push all the non-LFS objects to the remote.
  5. git push --tags in the local clone if needed.
  6. git lfs push --all origin master in the local clone to push all the LFS objects to the remote. If this is too large you can use the same tag-based partial push trick as in the previous section. It may or may not like having :master on the end — I found it worked fine with just a commit hash.

Finding repositories that haven’t been pushed

Something along these lines (from comments on https://stackoverflow.com/a/12499489):

find . -name .git -type d -print -exec git --git-dir={} --work-tree={}/.. cherry -v \;

Migrate a wiki repo to another GitBucket server

  1. Clone the original repository that contains the wiki (old-repo).
  2. Clone the actual wiki itself (old-wiki).
  3. Create empty new-repo on new server.
  4. Transfer ownership of new-repo if necessary. Do this before any of the remaining steps.
  5. In old-repo clone:
    git remote set-url origin <new-repo-url>
    git push
  6. In old-wiki clone:
    git remote set-url origin <new-wiki-url>
    git push -f
  7. Update wiki link in README.md of new-repo.
  8. Profit!