Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม Bash

เชี่ยวชาญ Bash One-Liners: Clone และจัดการ GitHub/GitLab Repositories แบบ Seamless

น้อยอย่างไรก็มีความพอใจมากกว่า One-liner Bash ที่ขลัง — อัตโนมัติงานนานชั่วโมงในบรรทัดเดียว

จากการสำรวจ Auto-recreate Laptop ด้วย Bash Scripts — ต้องการ Clone GitHub Repos ทั้งหมดไปเครื่องใหม่ — ได้ One-liner ที่ทำได้พอดี แล้วเขียนอีกตัวสำหรับ Backup ไป GitLab ด้วย

One-liner Clone ทุก GitHub Repositories

ข้อกำหนด: ต้องมีรายการ Repos ที่ต้องการ Clone — ให้เลือกได้ว่าอยากได้ Repo ไหนบ้าง (ไม่จำเป็น Clone ทั้งหมด)

Clone โดยไม่ใส่รหัสผ่านทุกครั้ง: HTTPS + Cached Credentials (15 นาที) หรือ SSH (แนะนำ) — สมมติ SSH Keys ตั้งค่าแล้ว

ไฟล์ gh-repos.txt (SSH URLs ทีละบรรทัด):

git@github.com:username/first-repository.git
git@github.com:username/second-repository.git
git@github.com:username/third-repository.git

รัน:

xargs -n1 git clone < gh-repos.txt

Clone ทุก Repo ในรายการเข้า Current Folder — ใช้กับ GitLab ได้เหมือนกัน (เปลี่ยน URLs)

ทำไมถึงทำงานได้?

2 ส่วน: Input (ขวา) + Action (ซ้าย) — เขียนสลับได้:

< gh-repos.txt xargs -n1 git clone
  • xargs -n1 = รันคำสั่งต่อ 1 Argument (1 บรรทัด)
  • git clone = คำสั่งที่จะรัน
  • Ta-da!

One-liner สร้างและ Push หลาย Repos บน GitLab

GitLab น่าสนใจ: สร้าง Repo ใหม่จาก Terminal ได้เลย (ไม่ต้อง Web UI) — Default เป็น Private (Public ต้องทำ Manual)

GitLab Docs แนะนำ git push --set-upstream แต่ไม่สะดวกสำหรับ Backup — อยาก Push ไป GitHub และ GitLab พร้อมกันด้วยคำสั่งเดียว

สร้าง gl-repos.txt จาก gh-repos.txt ด้วย Vim Search-Replace:

cp gh-repos.txt gl-repos.txt
vim gl-repos.txt
:%s/\<github\>/gitlab/g
:wq

ได้ gl-repos.txt:

git@gitlab.com:username/first-repository.git
git@gitlab.com:username/second-repository.git
git@github.com:username/third-repository.git

รัน One-liner สร้าง Repo + Add Remote + Push:

awk -F'\/|(\.git)' '{system("cd ~/FULL/PATH/" $2 " && git remote set-url origin --add " $0 " && git push")}' gl-repos.txt

⚠ ใส่ ~/FULL/PATH/ ให้ถูกต้อง = พาธเต็มไปยังโฟลเดอร์ที่ Clone GitHub Repos ไว้

Assumptions (ข้อสมมติ)

  1. ชื่อโฟลเดอร์ Local = ชื่อ Repo ใน URL (True หาก Clone ด้วย One-liner ข้างต้น)
  2. แต่ละ Repo อยู่ที่ Branch ที่ต้องการ Push (เช่น master)

ขยาย One-liner ให้ครอบคลุม Assumptions ได้ แต่จุดนั้นควรเขียน Bash Script แทน

ทำไมถึงทำงานได้? (Deep Dive)

Split Strings ด้วย awk

awk แยก Input ตาม Field Separator — Default Whitespace แต่อยากเปลี่ยนได้ด้วย -F — รองรับ Regex

Repo URL Format คงที่ → ดึงชื่อ Repo จากระหว่าง / และ .git ด้วย Regex \/|(\.git):

  • \/ = Escaped /
  • | = OR
  • (\.git) = Capture Group ท้าย URL (Cheat: .git ไม่ Split จริง แต่ตัดทิ้งง่าย)

Fields หลัง Split:

$1: git@gitlab.com:username
$2: first-repository
$0: ทั้ง URL เต็ม

สร้างคำสั่งด้วย Field Operators — Test ด้วย print ก่อน:

awk -F'\/|(\.git)' '{print "cd ~/FULL/PATH/" $2 " && git remote set-url origin --add " $0 " && git push"}' gl-repos.txt

Run Command ด้วย system()

system() สร้าง Child Process รันคำสั่ง → Return เมื่อเสร็จ — ทำให้รัน Git Commands ทีละ Repo โดยไม่หยุด Process หลักของ awk

คำสั่งสุดท้าย:

awk -F'\/|(\.git)' '{system("cd ~/FULL/PATH/" $2 " && git remote set-url origin --add " $0 " && git push")}' gl-repos.txt

ใช้ Backup ได้อย่างไร

Add GitLab URL เป็น Remote → git push โดยไม่มี Arguments จะ Push ไปทั้ง GitHub และ GitLab!

origin git@github.com:user/repo.git (fetch)
origin git@github.com:user/repo.git (push)
origin git@gitlab.com:user/repo.git (push)

git pull ดึงจาก Fetch Remote เดิม (GitHub) — Pull หลาย Remotes ซับซ้อนกว่า (Out of Scope)

ทำไมถึงใช้ One-liners?

One-liners เข้าใจยาก เขียนยาก อ่านยาก Debug ยาก — Missing Quote/Paren ง่าย — อธิบายยาว — ทำไมใช้?

Analogy: อ่านสูตรทำเค้กทีละขั้น → เข้าใจวิธี/ส่วนผสม → แต่ถ้าทิ้งส่วนผสมทุกอย่างเข้าเตาเรียงลำดับถูกต้อง → เค้กขึ้นมาทันที — นี่คือความพอใจของ One-liner!

Tools อย่าง xargs, awk ช่วยอัตโนมัติงานน่าเบื่อ — รู้จักพวกมันแล้ว จะช่วยชีวิตคุณได้มาก