คุณจัดระเบียบที่เก็บ git หลาย ๆ ที่เก็บสำรองไว้ด้วยกันได้อย่างไร


98

ด้วย SVN ฉันมีที่เก็บข้อมูลขนาดใหญ่เพียงแห่งเดียวที่ฉันเก็บไว้บนเซิร์ฟเวอร์และเช็คเอาต์ในเครื่องสองสามเครื่อง นี่เป็นระบบสำรองข้อมูลที่ค่อนข้างดีและช่วยให้ฉันทำงานกับเครื่องใดก็ได้อย่างง่ายดาย ฉันสามารถชำระเงินโปรเจ็กต์ที่เฉพาะเจาะจงยอมรับและอัปเดตโปรเจ็กต์ 'ต้นแบบ' หรือฉันสามารถชำระเงินทั้งหมดได้

ตอนนี้ฉันมีที่เก็บ git มากมายสำหรับโปรเจ็กต์ต่างๆซึ่งหลายแห่งอยู่ใน github ฉันยังมีที่เก็บ SVN ที่ฉันพูดถึงนำเข้าผ่านคำสั่ง git-svn ..

โดยพื้นฐานแล้วฉันชอบมีรหัสทั้งหมดของฉัน (ไม่ใช่แค่โปรเจ็กต์เท่านั้น แต่ตัวอย่างและสคริปต์แบบสุ่มบางอย่างเช่นประวัติย่อของฉันบทความที่ฉันเขียนเว็บไซต์ที่ฉันสร้างขึ้นและอื่น ๆ ) ในที่เก็บขนาดใหญ่ฉันสามารถโคลนลงในรีโมตได้อย่างง่ายดาย เครื่องหรือหน่วยความจำแท่ง / ฮาร์ดไดรฟ์เป็นข้อมูลสำรอง

ปัญหาคือเนื่องจากเป็นที่เก็บส่วนตัวและ git ไม่อนุญาตให้ตรวจสอบจากโฟลเดอร์เฉพาะ (ซึ่งฉันสามารถส่งไปที่ github เป็นโปรเจ็กต์แยกต่างหาก แต่มีการเปลี่ยนแปลงปรากฏทั้งใน master-repo และ sub- repos)

ฉันสามารถใช้ระบบโมดูลย่อย git แต่มันก็ไม่ได้ทำตามที่ฉันต้องการเช่นกัน (โมดูลย่อยเป็นตัวชี้ไปยังที่เก็บอื่น ๆ และไม่มีรหัสจริงดังนั้นจึงไม่มีประโยชน์สำหรับการสำรองข้อมูล)

ขณะนี้ฉันมีโฟลเดอร์ของ git-repos (ตัวอย่างเช่น ~ / code_projects / proj1 / .git / ~ / code_projects / proj2 / .git /) และหลังจากทำการเปลี่ยนแปลงกับ proj1 git push githubแล้วฉันก็คัดลอกไฟล์ไปที่ ~ / Documents / code / python / projects / proj1 / และทำการคอมมิตเดียว (แทนที่จะเป็นจำนวนมากในแต่ละ repos) แล้วทำgit push backupdrive1, git push mymemorystickฯลฯ

ดังนั้นคำถาม: โค้ดส่วนตัวและโปรเจ็กต์ของคุณมีที่เก็บ git อย่างไรและซิงค์และสำรองข้อมูลไว้อย่างไร

คำตอบ:


74

ฉันขอแนะนำอย่างยิ่งว่าอย่าใส่ข้อมูลที่ไม่เกี่ยวข้องในที่เก็บ Git ที่กำหนด ค่าใช้จ่ายในการสร้างที่เก็บใหม่ค่อนข้างต่ำและนั่นเป็นคุณสมบัติที่ทำให้สามารถแยกเชื้อสายต่างๆออกจากกันได้อย่างสมบูรณ์

การต่อสู้กับความคิดนั้นหมายถึงการจบลงด้วยประวัติศาสตร์ที่ยุ่งเหยิงโดยไม่จำเป็นซึ่งทำให้การบริหารงานยากขึ้นและที่สำคัญกว่านั้นคือเครื่องมือ "โบราณคดี" มีประโยชน์น้อยกว่าเนื่องจากผลจากการเจือจางที่เกิดขึ้น ตามที่คุณกล่าวมา Git ถือว่า "หน่วยของการโคลน" เป็นที่เก็บและในทางปฏิบัติต้องทำเช่นนั้นเนื่องจากลักษณะการกระจายของมัน

ทางออกหนึ่งคือเก็บทุกโครงการ / แพ็คเกจ / ฯลฯ เป็นที่ เก็บเปล่าของตัวเอง(กล่าวคือไม่มีต้นไม้ทำงาน) ภายใต้ลำดับชั้นที่มีความสุขเช่น:

/repos/a.git
/repos/b.git
/repos/c.git

เมื่อมีการกำหนดอนุสัญญาสองสามข้อแล้วการใช้การดำเนินการด้านการดูแลระบบ (การสำรองข้อมูลการบรรจุการเผยแพร่ทางเว็บ) กับลำดับชั้นที่สมบูรณ์จึงเป็นเรื่องเล็กน้อยซึ่งทำหน้าที่ได้ไม่ต่างจากที่เก็บ SVN "เสาหิน" การทำงานกับที่เก็บเหล่านี้จะค่อนข้างคล้ายกับเวิร์กโฟลว์ SVN ด้วยการเพิ่มที่ สามารถใช้การคอมมิตและสาขาในเครื่องได้:

svn checkout   --> git clone
svn update     --> git pull
svn commit     --> git push

คุณสามารถมีรีโมตหลายตัวในแต่ละโคลนที่ใช้งานได้เพื่อความสะดวกในการซิงโครไนซ์ระหว่างหลายฝ่าย:

$ cd ~/dev
$ git clone /repos/foo.git       # or the one from github, ...
$ cd foo
$ git remote add github ...
$ git remote add memorystick ...

จากนั้นคุณสามารถดึง / ดึงจาก "แหล่งที่มา" แต่ละรายการทำงานและคอมมิตในเครื่องจากนั้นกด ("สำรองข้อมูล") ไปยังรีโมตเหล่านี้เมื่อคุณพร้อมบางอย่างเช่น (สังเกตว่าจะผลักการกระทำและประวัติเดียวกันไปยัง รีโมทแต่ละอัน!):

$ for remote in origin github memorystick; do git push $remote; done

วิธีที่ง่ายที่สุดในการเปลี่ยนที่เก็บการทำงานที่มีอยู่ให้กลายเป็นที่เก็บ~/dev/foo เปล่าเช่นนี้:

$ cd ~/dev
$ git clone --bare foo /repos/foo.git
$ mv foo foo.old
$ git clone /repos/foo.git

ซึ่งส่วนใหญ่เทียบเท่ากับ a svn import- แต่อย่าโยนประวัติศาสตร์ "ท้องถิ่น" ที่มีอยู่ทิ้งไป

หมายเหตุ: โมดูลย่อยเป็นกลไกในการรวม เชื้อสายที่ใช้ร่วมกันดังนั้นฉันจะไม่คิดว่ามันเป็นเครื่องมือที่เหมาะสมสำหรับปัญหาที่คุณกำลังพยายามแก้ไข


18
ความจริงที่ว่าฉันยังคงลงเอยด้วยที่เก็บแยกต่างหากจำนวนมากและการเขียนสคริปต์ง่ายๆเพื่อช่วยจัดการพวกเขาทั้งหมดทำให้ฉันรู้สึกว่ามีบางอย่างหายไปในคอมไพล์ ฉันไม่สามารถตัดสินใจได้ว่ามันคืออะไรหรือจะทำอย่างไร
DonGar

คุณจัดการโครงการแยกกันเป็นจำนวนมากด้วยหรือไม่? ความสัมพันธ์แบบหนึ่งต่อหนึ่งระหว่างโปรเจ็กต์และที่เก็บให้ความรู้สึกสมเหตุสมผลในโลกแบบกระจาย แต่ฉันยังคงจัดที่เก็บเปล่าในแผนผังไดเร็กทอรีทั่วไปเพื่อความสะดวกในการสำรองข้อมูลและการดูแลระบบ (กล่าวอีกนัยหนึ่งคือ Git / Hg / Bzr บังคับให้คุณแยกการดูแลระบบออกจากงานโครงการในขณะที่เวิร์กโฟลว์ SVN ส่วนใหญ่รวมกันตอนนี้เป็นเรื่องปกติที่จะเห็นผู้คนมอบหมายส่วนการดูแลระบบให้กับ GitHub หรือผู้ให้บริการอื่น ๆ )
Damien Diederen

2
แนวคิดนี้เหมาะสมก็ต่อเมื่อคุณโฮสต์โครงการของคุณเองและ / หรือทั้งหมดเป็นโอเพ่นซอร์ส มิฉะนั้นคุณจะต้องใช้ github คุณจะต้องมีโครงการส่วนตัวไม่ จำกัด ซึ่งอาจมีราคาแพง
dkinzer

2
แทน "สำหรับระยะไกลในการให้กำเนิด GitHub MemoryStick; ทำคอมไพล์ผลักดัน $ ระยะไกลทำ" หนึ่งยังสามารถกำหนดค่าพิเศษระยะไกลที่จะผลักดันมีคำสั่งเดียวที่จะรีโมทหลายstackoverflow.com/questions/36862/... (อาจจะสะดวกกว่าในบางกรณี)
imz - Ivan Zakharyaschev

2
ฉันคิดว่าสิ่งที่ขาดหายไปคือวิธีที่คอมไพล์สามารถแยกอ็อบเจ็กต์ออกจากทรีย่อยเพื่อให้ "ที่เก็บ" เดียวสามารถประกอบด้วยการซิงโครไนซ์แยกต่างหากแม้ว่าหน่วยที่แยกกันได้ (ดาวน์โหลดทีละหน่วยโดยไม่มีส่วนที่เหลือ) เพื่อให้ผู้คนสามารถทำงานเฉพาะ ส่วนย่อยโดยไม่รู้เกี่ยวกับส่วนที่เหลือ
peterk

28

ฉันต้องการเพิ่มคำตอบของ Damienที่เขาแนะนำ:

$ for remote in origin github memorystick; do git push $remote; done

คุณสามารถตั้งค่ารีโมทพิเศษเพื่อส่งไปยังรีโมตจริงทั้งหมดด้วย 1 คำสั่ง ฉันพบที่http://marc.info/?l=git&m=116231242118202&w=2 :

ดังนั้นสำหรับ "git push" (ซึ่งเหมาะสมที่จะผลักกิ่งก้านเดียวกันหลาย ๆ ครั้ง) คุณสามารถทำสิ่งที่ฉันทำได้:

  • .git / config ประกอบด้วย:

    [remote "all"]
    url = master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
    url = login.osdl.org:linux-2.6.git
    
  • และตอนนี้git push all masterจะพุชสาขา "หลัก" ไปยัง ที่เก็บระยะไกลทั้งสอง

นอกจากนี้คุณยังสามารถบันทึกตัวเองที่พิมพ์ URL สองครั้งโดยใช้การสร้าง:

[url "<actual url base>"]
    insteadOf = <other url base>

3

ฉันยังอยากรู้เกี่ยวกับวิธีที่แนะนำในการจัดการสิ่งนี้และจะอธิบายการตั้งค่าปัจจุบันที่ฉันใช้ (กับ SVN) โดยพื้นฐานแล้วฉันได้สร้างที่เก็บที่มีลำดับชั้นของระบบไฟล์ขนาดเล็กรวมถึง bin และ lib dirs ของตัวเอง มีสคริปต์ในรูทของทรีนี้ที่จะตั้งค่าสภาพแวดล้อมของคุณเพื่อเพิ่ม bin, lib และอื่น ๆ เหล่านี้ให้กับตัวแปรสภาพแวดล้อมที่เหมาะสม ดังนั้นไดเรกทอรีรากจึงมีลักษณะดังนี้:

./bin/            # prepended to $PATH
./lib/            # prepended to $LD_LIBRARY_PATH
./lib/python/     # prepended to $PYTHONPATH
./setup_env.bash  # sets up the environment

ตอนนี้ภายใน / bin และ / lib มีหลายโครงการและและไลบรารีที่เกี่ยวข้อง ฉันรู้ว่านี่ไม่ใช่โครงการมาตรฐาน แต่คนอื่นในกลุ่มของฉันจะชำระเงิน repo ได้ง่ายมากเรียกใช้สคริปต์ 'setup_env.bash' และมีเวอร์ชันล่าสุดของโครงการทั้งหมดในเครื่อง เช็คเอาท์. พวกเขาไม่ต้องกังวลเกี่ยวกับการติดตั้ง / อัปเดต / usr / bin หรือ / usr / lib และช่วยให้การชำระเงินหลายรายการและสภาพแวดล้อมที่แปลเป็นภาษาท้องถิ่นเป็นเรื่องง่าย นอกจากนี้ใครบางคนสามารถ rm ที่เก็บข้อมูลทั้งหมดและไม่ต้องกังวลกับการถอนการติดตั้งโปรแกรมใด ๆ

วิธีนี้ใช้ได้ดีสำหรับเราและฉันไม่แน่ใจว่าเราจะเปลี่ยนหรือไม่ ปัญหาคือมีหลายโครงการในที่เก็บขนาดใหญ่แห่งนี้ มีวิธีมาตรฐาน git / Hg / bzr ในการสร้างสภาพแวดล้อมเช่นนี้และแยกโครงการออกเป็นที่เก็บของตนเองหรือไม่?


3

ฉันยังไม่ได้ลองซ้อนที่เก็บ git เพราะฉันยังไม่เจอสถานการณ์ที่ฉันต้องการ ตามที่ฉันอ่านใน#git channel git ดูเหมือนจะสับสนโดยการซ้อนที่เก็บกล่าวคือคุณกำลังพยายาม git-init ภายในที่เก็บ git วิธีเดียวในการจัดการโครงสร้างคอมไพล์ที่ซ้อนกันคือการใช้git-submoduleหรือrepoยูทิลิตี้ของ Android

สำหรับความรับผิดชอบในการสำรองข้อมูลที่คุณกำลังอธิบายนั้นฉันบอกว่ามอบสิทธิ์ให้ ... สำหรับฉันฉันมักจะใส่ที่เก็บ "ต้นทาง" สำหรับแต่ละโปรเจ็กต์ไว้ที่ไดรฟ์เครือข่ายในที่ทำงานซึ่งได้รับการสำรองข้อมูลเป็นประจำโดยเทคโนโลยีไอทีโดยใช้กลยุทธ์การสำรองข้อมูลของ ทางเลือก. มันง่ายและไม่ต้องกังวลกับมัน ;)


2

สิ่งที่เกี่ยวกับการใช้mrในการจัดการ Git repos หลายรายการพร้อมกัน:

คำสั่ง mr (1) สามารถเช็คเอาต์อัพเดตหรือดำเนินการอื่น ๆ บนชุดของที่เก็บราวกับว่าเป็นที่เก็บข้อมูลรวมกัน สนับสนุนการรวมกันของการโค่นล้ม, git, cvs, mercurial, bzr, darcs, cvs, vcsh, ที่เก็บฟอสซิลและความจริงและการสนับสนุนระบบควบคุมการแก้ไขอื่น ๆ สามารถเพิ่มได้อย่างง่ายดาย [... ]

สามารถกำหนดค่าได้อย่างมากผ่านเชลล์สคริปต์อย่างง่าย ตัวอย่างบางส่วนของสิ่งที่สามารถทำได้ ได้แก่ :

[... ]

  • เมื่ออัปเดตที่เก็บ git ให้ดึงจากต้นน้ำสองรายการที่แตกต่างกันและรวมทั้งสองเข้าด้วยกัน
  • รันการอัปเดตที่เก็บข้อมูลหลายรายการพร้อมกันซึ่งจะช่วยเร่งกระบวนการอัพเดตได้อย่างมาก
  • จดจำการกระทำที่ล้มเหลวเนื่องจากแล็ปท็อปออฟไลน์เพื่อให้สามารถลองใหม่ได้เมื่อกลับมาออนไลน์

1

มีอีกวิธีหนึ่งในการมี git repos ที่ซ้อนกัน แต่ไม่สามารถแก้ปัญหาที่คุณต้องการได้ อย่างไรก็ตามสำหรับคนอื่น ๆ ที่กำลังมองหาวิธีแก้ปัญหาที่ฉันเป็น:

ใน git repo ระดับบนสุดให้ซ่อนโฟลเดอร์ใน. gitignore ที่มี git repo ที่ซ้อนกัน สิ่งนี้ทำให้ง่ายต่อการมี git repos สองรายการแยกกัน (แต่ซ้อนกัน!)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.