Storing binary blobs in Git isn't a good idea since Git was mainly made to work with text files. However, it is possible to migrate existing blobs into Git LFS without too much trouble.
> [!Warning]
> This process will re-write the history of the repository, thus change commit hashes and can cause issues down the line.
> It is recommended to do a clean clone after the changes are pushed.
Before we begin anything, remember to have a clean backup of the repository somewhere. This process rarely fails, but it's always good to have backups just in case.
Also make sure you have [Git LFS](https://git-lfs.com/) installed on your machine.
In this example, we will assume our repository is a GitHub one named `contoso/super-app`.
We can first clone the repo bare:
```bash
~ git clone --bare
[email protected]:contoso/super-app.git
~ cd super-app.git
```
### Assessing the repository
To know what to migrate and how bad it is, we can use [git-sizer](https://github.com/github/git-sizer). This tool will tell you where the blobs are, how many, and how large they are.
Use either your package manager or the GitHub releases to download the tool and add it to your `PATH`.
While in the repository directory, we can now run git-sizer:
```bash
~ git-sizer --verbose
Processing blobs: 2364
Processing trees: 289
Processing commits: 45
Matching commits to trees: 45
Processing annotated tags: 0
Processing references: 4
| Name | Value | Level of concern |
| ---------------------------- | --------- | ------------------------------ |
| Overall repository size | | |
| * Commits | | |
| * Count | 45 | |
| * Total size | 16.8 KiB | |
| * Trees | | |
| * Count | 289 | |
| * Total size | 141 KiB | |
| * Total tree entries | 3.52 k | |
| * Blobs | | |
| * Count | 2.36 k | |
| * Total size | 48.3 MiB | |
| * Annotated tags | | |
| * Count | 0 | |
| * References | | |
| * Count | 4 | |
| * Branches | 1 | |
| * Tags | 3 | |
| | | |
| Biggest objects | | |
| * Commits | | |
| * Maximum size [1] | 1.14 KiB | |
| * Maximum parents [1] | 2 | |
| * Trees | | |
| * Maximum entries [2] | 97 | |
| * Blobs | | |
| * Maximum size [3] | 34.6 MiB | *** |
| | | |
| History structure | | |
| * Maximum history depth | 42 | |
| * Maximum tag depth | 0 | |
| | | |
| Biggest checkouts | | |
| * Number of directories [4] | 60 | |
| * Maximum path depth [4] | 8 | |
| * Maximum path length [4] | 106 B | * |
| * Number of files [4] | 711 | |
| * Total size of files [5] | 75.9 MiB | |
| * Number of symlinks | 0 | |
| * Number of submodules | 0 | |
[1] 752ad3acc48b861c392b54521cca4dc0007082df (refs/heads/master)
[2] be2c6146b64de3b80900e86d2bdfedc82e7ad04b (refs/heads/master:OggVorbisEncoder/Setup/Templates/FloorBooks)
[3] 1b40fc5739d441436b4ba3533588fe31c3bdb318 (refs/heads/master:OggVorbisEncoder.Example/unencoded.raw)
[4] 3c34fe2f36d8a962b829b0ddcccda97a3216d2c3 (refs/heads/master^{tree})
[5] ddb22eb491e16c5061715a99c5bfc78ca81c62be (6dd75e71124bd52b73df1af50c5b1131a4d64292^{tree})
```
In our case, we can see that the largest blob is around 34.6MiB. We can also see that the file in question is a `.raw`.
To have more insights as to what's there, we can also run the following:
```bash
~ git lfs migrate info --everything
Sorting commits: ..., done.
Examining commits: 100% (45/45), done.
*.raw 114 MB 4/4 files 100%
*.cs 6.7 MB 2291/2291 files 100%
*.ogg 1.8 MB 1/1 file 100%
*.dll 512 KB 1/1 file 100%
*.csproj 101 KB 36/36 files 100%
```
We can now see a bunch of `.raw`, `.ogg` and `.dll` files, which are the extensions we will be targetting.
### Migrating to LFS
Migrating to LFS is easy:
```bash
~ git lfs migrate import --everything --verbose --include "*.raw,*.ogg,*.dll"
```
Depending on how large the repository history is, this might take a while, but once it is finished, your repository is now using Git LFS!
You can then re-run the info command to see what's been migrated:
```bash
~ git lfs migrate info --everything
Sorting commits: ..., done.
Examining commits: 100% (45/45), done.
*.cs 6.7 MB 2291/2291 files 100%
*.csproj 101 KB 36/36 files 100%
*.sln 20 KB 5/5 files 100%
*.gitignore 9.8 KB 2/2 files 100%
*.md 9.5 KB 12/12 files 100%
LFS Objects 116 MB 6/6 files 100%
```
You can then push everything to the repo:
```bash
~ git push --all --force
```
And you should be all set.
In any case the LFS files aren't pushed automatically, you can also do:
```bash
~ git lfs push --all
```
All future occurrences of the file types you specified in the `migrate` command will automatically get added to Git LFS.
If you want to track a new file extension without having to redo the migration, issue this command before adding the blob:
```bash
~ git lfs track "*.<extension>"
```
For instance:
```bash
~ git lfs track "*.png"
```