Commit 6fe2867c47

6fe2867c47efc209b255fc3e0b73dd5b79751baa

parent: 09529db2c2

Unsigned

cmc <hello@cleberg.net> · 2025-04-06 04:48 UTC

add new post: git-mirror

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
7This is a short post detailing how I maintained repositories on GitHub and
8mirrors on GitLab - including both public and private repositories.
9
10Since GitLab locks pull-only mirrors behing their Premium and Ultimate tiers, I
11found a different solution.
12
13* Creating Mirrors
14
15I'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
25To start, I navigated to the =~/git= directory, which holds all of the
26repositories I have on GitHub and created a shell script.
27
28#+begin_src shell
29cd ~/git
30nano setup_mirrors.sh
31#+end_src
32
33Within this shell script, I created a loop that will open each repository and
34add both the GitHub and GitLab SSH-style clone URIs to the =origin= remote.
35
36#+begin_src shell
37for repo in */
38do
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 ..
44done
45#+end_src
46
47Once complete, I created another shell script to open each repository, pull any
48remote commits, and push local commits to both remotes.
49
50#+begin_src shell
51nano mirror.sh
52#+end_src
53
54#+begin_src shell
55for repo in */;
56do
57 cd $repo
58 git pull --rebase origin HEAD
59 git push
60 cd ..
61done
62#+end_src
63
64Finally, enable execution of both scripts before moving on.
65
66#+begin_src shell
67chmod +x setup_mirrors.sh
68chmod +x mirror.sh
69#+end_src
70
71* Initialize Mirrors
72
73To 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
79Once complete, each repository /should/ have one fetch URI (GitHub) and two push
80URIs (GitHub & GitLab). At this point, any =git pull= or =git fetch= commands
81will pull from GitHub and any =git push= commands will send updates to both
82GitHub and GitLab.
83
84* Schedule Periodic Checks
85
86To utilize the =mirror.sh= script from the previous step, let's use crontab.
87
88#+begin_src shell
89crontab -e
90#+end_src
91
92Within crontab, I used the schedule below to ensure the script is executed
93daily.
94
95#+begin_src text
960 0 * * * /Users/cmc/git/mirror.sh
97#+end_src
98
99This ensures that the =mirror.sh= file is executed daily and will push any local
100or GitHub commits to GitLab.
101
102I have tested this by manually running =mirror.sh= and watching the results.
103There are edge cases where I will need to intervene and manually resolve merge
104conflicts, 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 <h2>Recent Blog Posts</h2> 10 <h2>Recent Blog Posts</h2>
11 11
12 <div class="post"> 12 <div class="post">
13 <time datetime="2025-02-24 19:20:05">2025-02-24</time> 13 <time datetime="2025-04-05 23:04:54">2025-04-05</time>
14 <a href="/blog/email-migration.html" >A Painful Email Migration</a> 14 <a href="/blog/git-mirror.html">Mirroring my Repositories from GitHub to
15 GitLab</a>
15 </div> 16 </div>
16 17
17 <div class="post"> 18 <div class="post">
18 <time datetime="2025-02-11 11:40:00">2025-02-11</time> 19 <time datetime="2025-02-24 19:20:05">2025-02-24</time>
19 <a href="/blog/obscura-vpn.html">A Review of Obscura VPN: A Two-Party VPN</a> 20 <a href="/blog/email-migration.html">A Painful Email Migration</a>
20 </div> 21 </div>
21 22
22 <div class="post"> 23 <div class="post">
23 <time datetime="2025-01-23 20:44:00">2025-01-23</time> 24 <time datetime="2025-02-11 11:40:00">2025-02-11</time>
24 <a href="/blog/self-hosting-tandoor.html">Self-Hosting Tandoor Recipe Manager</a> 25 <a href="/blog/obscura-vpn.html">A Review of Obscura VPN: A Two-Party VPN</a>
25 </div> 26 </div>
26 27
27 <br /> 28 <br />