Well it's no brainer that moving content from one git repo to another can be a complex task, especially if you want to preserve the commit history. In this tutorial I will show you step by step instructions with the commands to be used for moving directory or files from one Git repo to another with a practical example.
I have created two repositories in GitLab:
- source-repo: This will be our source repo from which we will move the content
- target-repo: We will be moving content from
source-repo
totarget-repo
.
In a nut-shell here are the important set of commands which we will use to move the content from one Git repo to another:
# Step 1: Install git-filter-repo
pip install git-filter-repo
# Step 2: Clone the Source Repository
git clone <url-of-source-repo> source-repo
cd source-repo
# Step 3: Filter the Desired Directory
git filter-repo --path dir1/ --force
# Step 4: Clone the Target Repository
cd ..
git clone <url-of-target-repo> target-repo
cd target-repo
# Step 5: Add the Source Repository as a Remote
git remote add source ../source-repo
git fetch source
# Step 6: Merge the Filtered History
git checkout -b import-branch
git merge source/main --allow-unrelated-histories
# Step 7: Clean Up and Push
git remote remove source
git checkout main
git merge import-branch
git branch -d import-branch
git push origin main
Now we will demonstrate the usage of these commands in detail in the remaining article:
Step 1. Install git-filter-repo
Git repositories can contain numerous files and directories, each with its own history of changes. If you want to move only a specific directory (e.g., new-directory
), filtering allows you to isolate the commit history related to that directory. This way, the new repository doesn't include unrelated commit history, making it cleaner and more focused. Also by filtering out unnecessary parts of the repository, you reduce the size of the new repository.
You can use git filter-branch
or git subtree
to achieve this. Both methods effectively rewrite the commit history to include only the changes related to the specified directory.
We will be using git filter-branch but first let's make sure this is installed in our environment:
pip3 install git-filter-repo
Since it is installed in our user's home directory so we will need to update the PATH variable to also refer the new path so that we can run the command without specifying absolute path:
export PATH=$PATH:/home/deepak/.local/bin
Although this command is non-persistent and will not survive reboot. To make it persistent you can add it to system profile, read more at .bashrc vs .bash_profile [Which one to use?]
Step 2: Clone the Source Repository
Clone your source repository to a local directory.
git clone git@gitlab.com:golinuxcloud/source-repo.git
Navigate into the source repository:
cd source-repo
Now I have created some dummy commits and directories/files which I will use for demonstration:
In this example I will move dir1
from source-repo
to target-repo
.
Step 3. Filter Out the Desired File or Directory
Use git-filter-repo
to filter out the file or directory you want to move. This will rewrite the repository to only include the specified path.
git filter-repo --path dir1/ --force
Step 4. Clone Target Repository
Navigate to the parent directory, clone the target-repo
from the remote URL, and change into its directory.
cd ..
git clone git@gitlab.com:golinuxcloud/target-repo.git
cd target-repo
Step 5. Add the Source Repository as a Remote
Add the filtered source-repo
as a remote repository named source
to the target-repo
. Fetch all the branches and commits from this remote.
git remote add source ../source-repo
git fetch source
Step 6. Merge the Filtered History into Target Repository
Create and switch to a new branch named import-branch
. Merge the main
branch from the source
remote into the import-branch
, using the --allow-unrelated-histories
flag to handle unrelated commit histories.
git checkout -b import-branch
git merge source/main --allow-unrelated-histories
Step 7. Clean Up and Push Changes to Target Repository
Remove the source
remote, switch back to the main
branch, merge the import-branch
into the main
branch, delete the import-branch
, and push the changes to the remote main
branch of the target-repo
.
git remote remove source
git checkout main
git merge import-branch
git branch -d import-branch
git push origin main
Step 8. Verify the moved content into new Git repository
Now you can login to GitLab GUI and verify the newly moved directory and it's commit history:
So, we have successfully moved directory and files from one Git repo to another without loosing commit history.
Summary
It is easy to move content from one git repo to another by following straightforward steps. It starts by understanding the key commands needed in the process. You then dive into a step-by-step transfer of the target content, ensuring you preserve the history.
As explained in this tutorial, you can move content between the same server repositories or repositories of different code tracking servers.