Skip to content

Commit 23348b8

Browse files
committed
updating migration lfs post title and elaborating on alternative method
1 parent c5a940b commit 23348b8

File tree

3 files changed

+63
-19
lines changed

3 files changed

+63
-19
lines changed

_posts/2023-09-07-add-files-to-git-lfs.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ image:
1818
Git LFS can be very helpful to store large files along with your code in Git repositories. Git LFS artifacts are treated like any other file in Git, but the contents of the file are stored in a separate location. This allows you to store large files in Git without bloating the size of your Git repository. Tracking new files in Git LFS is easy, but there are a few steps you need to follow when using LFS for the first time.
1919

2020
> See my other Git LFS posts:
21-
> - [Migrating Git Repos with LFS Artifacts](/posts/migrate-git-lfs-artifacts/)
21+
> - [Migrating GitHub Repositories: Tackling Files in Git LFS](/posts/migrate-git-lfs-artifacts/)
2222
> - [Migrating Large Files in Git to Git LFS](/posts/migrate-to-git-lfs/)
2323
{: .prompt-info }
2424

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
2-
title: 'Migrating Git Repos with LFS Artifacts'
2+
title: 'Migrating GitHub Repositories: Tackling Files in Git LFS'
33
author: Josh Johanning
44
date: 2023-09-07 14:30:00 -0500
5-
description: How to migrate Git LFS artifacts from one repository to another
5+
description: How to migrate Git LFS objects from one repository to another
66
categories: [GitHub, Migrations]
77
tags: [GitHub, Migrations, Git, Git LFS]
88
media_subpath: /assets/screenshots/2023-09-07-migrate-git-lfs-artifacts
@@ -15,7 +15,14 @@ image:
1515

1616
## Overview
1717

18-
Git Large File Storage (LFS) replaces large files such as audio samples, videos, datasets, and graphics with text pointers inside Git, while storing the file contents on a remote server like GitHub. Git LFS works seamlessly, you hardly know it's there when interacting with Git. However, there are special instructions that you need to follow if you are migrating Git repositories that contain LFS artifacts.
18+
Git Large File Storage (LFS) replaces large files such as audio samples, videos, datasets, and graphics with text pointers inside Git, while storing the file contents on a remote server like GitHub. Git LFS works seamlessly, you hardly know it's there when interacting with Git.
19+
20+
You can migrate repositories to GitHub using [GitHub Enterprise Importer (GEI)](https://docs.github.com/en/migrations/using-github-enterprise-importer/understanding-github-enterprise-importer/about-github-enterprise-importer), however, since Git LFS is an extension to Git, they are [not migrated](https://docs.github.com/en/migrations/using-github-enterprise-importer/migrating-between-github-products/about-migrations-between-github-products#data-that-is-not-migrated) automatically. There are special instructions that you need to follow if you are migrating Git repositories that contain LFS objects.
21+
22+
This post highlights two methods to migrate Git LFS objects from one repository to another:
23+
24+
- [Method 1: Using `git lfs push --all` to migrate all LFS objects](#method-1-git-lfs-push---all)
25+
- [Method 2: Methodically pushing each LFS object](#method-2-methodically-pushing-each-object) (slower but more reliable for large repos and instances with higher network latency)
1926

2027
> See my other Git LFS posts:
2128
> - [Migrating Large Files in Git to Git LFS](/posts/migrate-to-git-lfs/)
@@ -29,50 +36,87 @@ Git Large File Storage (LFS) replaces large files such as audio samples, videos,
2936
- On Windows, `git lfs` should be installed with [Git for Windows](https://gitforwindows.org/), but you can install an updated version via `choco install git-lfs`
3037
2. Once installed, you need to run `git lfs install` to configure Git hooks to use LFS.
3138

32-
## Migrating a Repository with LFS Artifacts
39+
## Migrating a Repository with LFS Objects
40+
41+
No matter which method you choose, if you are using GEI to migrate the repository, you should run the migration first. This will migrate the Git repository, including the text pointers for the LFS objects, as well metadata such as pull requests and issues. After the migration is complete, you can then run one of the methods below to migrate the LFS objects.
42+
43+
> If you use GEI, I recommend waiting for the migration to fully complete before pushing LFS objects. However, if time is critical, you can proceed once the repository and code are visible in GitHub.
44+
{: .prompt-tip }
3345

34-
If you are migrating a repository that contains LFS artifacts, you need to make sure that you migrate the LFS artifacts as well. If you don't, you will end up with a repository that contains text pointers to files that don't exist. This is because the LFS artifacts are stored in a separate location from the repository itself.
46+
### Method 1: git lfs push --all
47+
48+
If you are migrating a repository that contains LFS objects, you need to make sure that you migrate the LFS objects as well. If you don't, you will end up with a repository that contains text pointers to files that don't exist. This is because the LFS objects are stored in a separate location from the repository itself.
3549

3650
Instructions:
3751

3852
```bash
3953
git clone --mirror <source-url> temp
4054
cd temp
41-
git push --mirror <target-url>
55+
# git push --mirror <target-url> # or migrate with GEI
4256
git lfs fetch --all
4357
git lfs push <target-url> --all
4458
```
59+
{: .nolineno}
4560

46-
For Git repos with LFS, the two `git lfs` commands are key. This `git lfs fetch --all` command will download all the LFS artifacts from the source repository and store them in the target repository. The `git lfs push <target-url> --all` command will push all of the LFS artifacts to the target repository. After the push, the text pointers will be updated - including the same commit hash!
61+
For Git repos with LFS, the two `git lfs` commands are key. This `git lfs fetch --all` command will download all the LFS objects from the source repository and store them in the target repository. The `git lfs push <target-url> --all` command will push all of the LFS objects to the target repository. After the push, the text pointers will be updated - including the same commit hash!
4762

48-
Here is an example of migrating a repository that contains LFS artifacts:
63+
Here is an example of migrating a repository that contains LFS objects:
4964
![Git LFS commands](git-lfs-commands.png){: .shadow }
50-
_Running the migration commands to migrate a Git repository including Git LFS artifacts_
65+
_Running the migration commands to migrate a Git repository including Git LFS objects_
5166

52-
The repository has been migrated, including the LFS artifacts:
67+
The repository has been migrated, including the LFS objects:
5368
![Git LFS file in GitHub](git-lfs-light.png){: .shadow }{: .light }
5469
![Git LFS file](git-lfs-dark.png){: .shadow }{: .dark }
5570
_File stored in Git LFS file in GitHub_
5671

57-
## Alternative Method
72+
### Method 2: methodically pushing each object
5873

59-
The method above worked well for me in my tests, even in tests with 1,000 LFS artifacts each 1mb in size. However, I have seen issues running these commands for some customers with larger repositories. Sometimes the `git lfs fetch` or `git lfs push` will hang or not appear to migrate all of the LFS artifacts. If you run into issues, you can run this script to more thoroughly (but slower) way to migrate the LFS artifacts. It works by looping through each LFS object and pushing it individually pushing it.
74+
The method above worked well for me in my tests, even in tests with 1,000 LFS objects each 1mb in size. However, I have seen issues running these commands for some customers with larger repositories. Sometimes the `git lfs fetch` or `git lfs push` will hang or not appear to migrate all of the LFS objects. If you run into issues, you can run this script a more thorough (but slower) way to migrate the LFS objects. It works by looping through each LFS object and individually pushing it.
6075

61-
The alternative script to migrate the LFS artifacts to another repository:
76+
The alternative script to migrate the LFS objects to another repository:
6277

6378
```bash
64-
git clone --mirror <source-url> temp
79+
SOURCEURL=https://github.com/source-org/source-repo.git
80+
TARGETURL=https://github.com/target-org/target-repo.git
81+
git clone --mirror $SOURCEURL temp
6582
cd temp
83+
# git push --mirror <target-url> # or migrate with GEI
84+
git lfs fetch --all origin
6685
for object_id in $(git lfs ls-files --all --long | awk '{print $1}'); do
67-
git lfs push --object-id remote "$object_id"
86+
git lfs push --object-id $TARGETURL "$object_id"
6887
done
6988
```
89+
{: .nolineno}
7090

7191
> Source for the [script](https://github.com/git-lfs/git-lfs/issues/4899#issuecomment-1688588756).
7292
{: .prompt-info }
7393

94+
You could speed this up by using `xargs` and parallelization techniques. Something like this:
95+
96+
```bash
97+
git lfs ls-files --all --long | awk '{print $1}' | xargs -P 4 -I {} git lfs push --object-id $TARGETURL {}
98+
```
99+
{: .nolineno}
100+
101+
> Parallelization is much harder to debug! I would recommend starting with the non-parallel version first and only use this sample if you had an extremely large number of LFS objects and are comfortable debugging any issues that might arise.
102+
{: .prompt-warning }
103+
104+
## Other Tips
105+
106+
To speed up the migration process, you can prioritize the main branch since developers typically work with LFS files on the default branch most often. Instead of migrating all LFS objects at once, migrate the main branch first, then handle other branches as needed. You can do this by omitting the `--all` flag to only migrate LFS objects reachable from the current branch:
107+
108+
```bash
109+
git clone --mirror <source-url> temp
110+
cd temp
111+
# git push --mirror <target-url> # or migrate with GEI
112+
git lfs fetch
113+
git lfs push <target-url>
114+
# now use the `--all` option or for loop to migrate all other reachable LFS objects
115+
```
116+
{: .nolineno}
117+
74118
## Summary
75119

76-
Migrating Git repositories is simple. However, if the repository contains LFS artifacts, you need to make sure to run the `git lfs fetch` and `git lfs push` commands to migrate them along with the repository. If you don't, your Git LFS files will be missing.
120+
Migrating Git repositories is simple. However, if the repository contains LFS objects, you need to make sure to run the `git lfs fetch` and `git lfs push` commands to migrate them along with the repository. If you don't, your Git LFS files will be missing.
77121

78-
Now that your Git repo, including LFS artifacts, is migrated, you can delete the temp folder, update remotes on your local repo, and continue working as normal! 🚀
122+
Now that your Git repo, including LFS objects, is migrated, you can delete the temp folder (`cd .. && rm -rf temp`), update remotes on your local repo (`git remote remove origin` / `git remote add origin <url>`), and continue working as normal! 🚀

_posts/2023-09-07-migrate-to-git-lfs.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ If you've ever tried migrating or pushing a repository that contains a file larg
2525
This post will show you how to migrate large blobs in Git to Git LFS.
2626

2727
> See my other Git LFS posts:
28-
> - [Migrating Git Repos with LFS Artifacts](/posts/migrate-git-lfs-artifacts/)
28+
> - [Migrating GitHub Repositories: Tackling Files in Git LFS](/posts/migrate-git-lfs-artifacts/)
2929
> - [Adding Files to Git LFS](/posts/add-files-to-git-lfs/)
3030
{: .prompt-info }
3131

0 commit comments

Comments
 (0)