น้อยอย่างไรก็มีความพอใจมากกว่า 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 (ข้อสมมติ)
- ชื่อโฟลเดอร์ Local = ชื่อ Repo ใน URL (True หาก Clone ด้วย One-liner ข้างต้น)
- แต่ละ 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 ช่วยอัตโนมัติงานน่าเบื่อ — รู้จักพวกมันแล้ว จะช่วยชีวิตคุณได้มาก