Commit 6fe2867c47
Unsigned
Layout: unified · split
content/blog/2025-04-05-git-mirror.org added +104
| @@ -0,0 +1,104 @@ | ||
| 1 | #+date: <2025-04-05 Sat 23:04:54> | |
| 2 | #+title: Mirroring my Repositories from GitHub to GitLab | |
| 3 | #+description: Read to learn how I was able to efficiently make sure all of my repositories are mirrored from GitHub to GitLab. | |
| 4 | #+filetags: :git: | |
| 5 | #+slug: git-mirror | |
| 6 | ||
| 7 | This is a short post detailing how I maintained repositories on GitHub and | |
| 8 | mirrors on GitLab - including both public and private repositories. | |
| 9 | ||
| 10 | Since GitLab locks pull-only mirrors behing their Premium and Ultimate tiers, I | |
| 11 | found a different solution. | |
| 12 | ||
| 13 | * Creating Mirrors | |
| 14 | ||
| 15 | I'll skip the setup and just hit the bullet points: | |
| 16 | ||
| 17 | - I have a plethora of GitHub repositories. | |
| 18 | - I used GitLab's mass-import functionality to do the initial import of my | |
| 19 | repositories from GitHub. | |
| 20 | - I made sure all of my GitHub repositories were cloned locally in my =~/git= | |
| 21 | directory. | |
| 22 | ||
| 23 | * Setting up Mirror Connections | |
| 24 | ||
| 25 | To start, I navigated to the =~/git= directory, which holds all of the | |
| 26 | repositories I have on GitHub and created a shell script. | |
| 27 | ||
| 28 | #+begin_src shell | |
| 29 | cd ~/git | |
| 30 | nano setup_mirrors.sh | |
| 31 | #+end_src | |
| 32 | ||
| 33 | Within this shell script, I created a loop that will open each repository and | |
| 34 | add both the GitHub and GitLab SSH-style clone URIs to the =origin= remote. | |
| 35 | ||
| 36 | #+begin_src shell | |
| 37 | for repo in */ | |
| 38 | do | |
| 39 | cd $repo | |
| 40 | git remote set-url origin --push --add git@github.com:ccleberg/${repo%*/}.git | |
| 41 | git remote set-url origin --push --add git@gitlab.com:ccleberg/${repo%*/}.git | |
| 42 | git remote -v | |
| 43 | cd .. | |
| 44 | done | |
| 45 | #+end_src | |
| 46 | ||
| 47 | Once complete, I created another shell script to open each repository, pull any | |
| 48 | remote commits, and push local commits to both remotes. | |
| 49 | ||
| 50 | #+begin_src shell | |
| 51 | nano mirror.sh | |
| 52 | #+end_src | |
| 53 | ||
| 54 | #+begin_src shell | |
| 55 | for repo in */; | |
| 56 | do | |
| 57 | cd $repo | |
| 58 | git pull --rebase origin HEAD | |
| 59 | git push | |
| 60 | cd .. | |
| 61 | done | |
| 62 | #+end_src | |
| 63 | ||
| 64 | Finally, enable execution of both scripts before moving on. | |
| 65 | ||
| 66 | #+begin_src shell | |
| 67 | chmod +x setup_mirrors.sh | |
| 68 | chmod +x mirror.sh | |
| 69 | #+end_src | |
| 70 | ||
| 71 | * Initialize Mirrors | |
| 72 | ||
| 73 | To use the =setup_mirrors.sh= script above, simply execute it from a terminal. | |
| 74 | ||
| 75 | #+begin_src shell | |
| 76 | ./setup_mirrors.sh | |
| 77 | #+end_src | |
| 78 | ||
| 79 | Once complete, each repository /should/ have one fetch URI (GitHub) and two push | |
| 80 | URIs (GitHub & GitLab). At this point, any =git pull= or =git fetch= commands | |
| 81 | will pull from GitHub and any =git push= commands will send updates to both | |
| 82 | GitHub and GitLab. | |
| 83 | ||
| 84 | * Schedule Periodic Checks | |
| 85 | ||
| 86 | To utilize the =mirror.sh= script from the previous step, let's use crontab. | |
| 87 | ||
| 88 | #+begin_src shell | |
| 89 | crontab -e | |
| 90 | #+end_src | |
| 91 | ||
| 92 | Within crontab, I used the schedule below to ensure the script is executed | |
| 93 | daily. | |
| 94 | ||
| 95 | #+begin_src text | |
| 96 | 0 0 * * * /Users/cmc/git/mirror.sh | |
| 97 | #+end_src | |
| 98 | ||
| 99 | This ensures that the =mirror.sh= file is executed daily and will push any local | |
| 100 | or GitHub commits to GitLab. | |
| 101 | ||
| 102 | I have tested this by manually running =mirror.sh= and watching the results. | |
| 103 | There are edge cases where I will need to intervene and manually resolve merge | |
| 104 | conflicts, but it's largely autonomous, so I'm happy with the results. | |
theme/templates/index.html +7 −6
| @@ -10,18 +10,19 @@ sub rsa4096 2022-11-16 [E]</pre> | ||
| 10 | 10 | <h2>Recent Blog Posts</h2> |
| 11 | 11 | |
| 12 | 12 | <div class="post"> |
| 13 | <time datetime="2025-02-24 19:20:05">2025-02-24</time> | |
| 14 | <a href="/blog/email-migration.html" >A Painful Email Migration</a> | |
| 13 | <time datetime="2025-04-05 23:04:54">2025-04-05</time> | |
| 14 | <a href="/blog/git-mirror.html">Mirroring my Repositories from GitHub to | |
| 15 | GitLab</a> | |
| 15 | 16 | </div> |
| 16 | 17 | |
| 17 | 18 | <div class="post"> |
| 18 | <time datetime="2025-02-11 11:40:00">2025-02-11</time> | |
| 19 | <a href="/blog/obscura-vpn.html">A Review of Obscura VPN: A Two-Party VPN</a> | |
| 19 | <time datetime="2025-02-24 19:20:05">2025-02-24</time> | |
| 20 | <a href="/blog/email-migration.html">A Painful Email Migration</a> | |
| 20 | 21 | </div> |
| 21 | 22 | |
| 22 | 23 | <div class="post"> |
| 23 | <time datetime="2025-01-23 20:44:00">2025-01-23</time> | |
| 24 | <a href="/blog/self-hosting-tandoor.html">Self-Hosting Tandoor Recipe Manager</a> | |
| 24 | <time datetime="2025-02-11 11:40:00">2025-02-11</time> | |
| 25 | <a href="/blog/obscura-vpn.html">A Review of Obscura VPN: A Two-Party VPN</a> | |
| 25 | 26 | </div> |
| 26 | 27 | |
| 27 | 28 | <br /> |