การจัดการไฟล์ไบนารีขนาดใหญ่ด้วย Git


523

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

  1. คัดลอกไฟล์ไบนารีด้วยมือ
    • Pro: ไม่แน่ใจ
    • Contra: ฉันต่อต้านสิ่งนี้อย่างมากเนื่องจากจะเพิ่มโอกาสเกิดข้อผิดพลาดเมื่อตั้งค่าไซต์ใหม่ / ย้ายข้อมูลเก่า สร้างอุปสรรค์อื่นที่จะใช้
  2. จัดการกับพวกเขาทั้งหมดที่มีGit
    • Pro: ลบความเป็นไปได้ที่จะ 'ลืม' เพื่อคัดลอกไฟล์สำคัญ
    • Contra: ขยายพื้นที่เก็บข้อมูลและลดความยืดหยุ่นในการจัดการรหัสฐานและชำระเงินโคลน ฯลฯ จะใช้เวลาสักครู่
  3. แยกที่เก็บ
    • Pro: การตรวจสอบ / การโคลนรหัสที่มานั้นรวดเร็วและภาพนั้นถูกเก็บถาวรอย่างถูกต้องในพื้นที่เก็บข้อมูลของตัวเอง
    • Contra: ลบความเรียบง่ายของการมีที่เก็บ Git หนึ่งเดียวในโครงการ มันแนะนำสิ่งอื่น ๆ ที่ฉันไม่ได้คิด

คุณมีประสบการณ์ / ความคิดเกี่ยวกับเรื่องนี้อย่างไร

นอกจากนี้: ไม่มีใครมีประสบการณ์กับที่เก็บ Git หลายแห่งและจัดการกับพวกเขาในโครงการเดียวหรือไม่?

ไฟล์เป็นรูปภาพสำหรับโปรแกรมที่สร้าง PDF พร้อมไฟล์เหล่านั้น ไฟล์จะไม่เปลี่ยนแปลงบ่อยนัก (เหมือนในปีที่ผ่านมา) แต่ไฟล์เหล่านี้เกี่ยวข้องกับโปรแกรมมาก โปรแกรมจะไม่ทำงานหากไม่มีไฟล์


26
แล้วเมื่อรุ่นจำเป็นต้องมีการควบคุมไฟล์ไบนารีล่ะ? ฉันกำลังคิดสำหรับทีมศิลปินที่ทำงานด้านทรัพย์สิน
Dan

3
ถ้าจำเป็นคุณต้องสร้างความสมดุลของทรัพยากรที่มีอยู่ (ดิสก์แบนด์วิดท์เวลา CPU) กับผลประโยชน์ที่คุณได้รับ
ปี่

4
โปรดทราบว่าหากไม่มีการล็อกไฟล์ git นั้นไม่ดีเมื่อมีหลายคนที่ต้องทำงานกับไฟล์ไบนารีเดียวกัน
yoyo

1
VonC

1
ที่นี่พวกเขาเป็นbestechvideos.com/tag/gitcasts
doughgle

คำตอบ:


177

หากโปรแกรมไม่ทำงานหากไม่มีไฟล์ดูเหมือนว่าการแยกไฟล์เหล่านั้นเป็น repo แยกเป็นความคิดที่ไม่ดี เรามีห้องทดสอบขนาดใหญ่ที่เราแบ่งเป็น repo แยกต่างหาก แต่มันเป็นไฟล์ "เสริม" อย่างแท้จริง

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

นี่คือการแนะนำที่ดีสำหรับ submodulesจาก Git Book


11
"ตามที่ฉันเข้าใจคุณจะได้รับการแก้ไขที่เกี่ยวข้องกับภาพของคุณเท่านั้น submodule" ฉันไม่คิดว่ามันถูกต้อง
Robin Green

22
จริง submodule เป็นที่เก็บ Git เต็มรูปแบบซึ่งเพิ่งเกิดขึ้นซ้อนภายในที่เก็บข้อมูลหลัก มันรู้ประวัติศาสตร์ทั้งหมดของมัน คุณสามารถคอมมิทบ่อยครั้งได้ แต่ถ้าคุณเก็บสิ่งเดียวกันไว้ในนั้นคุณจะมีในพาเรนต์มันจะมีปัญหาแบบเดียวกับที่พาเรนต์มี
Cascabel

5
นี่เป็นวิธีที่ไม่ดีถ้าคุณมีไฟล์ไบนารีขนาดใหญ่ที่มีการเปลี่ยนแปลงในช่วงเวลาปกติ เรามีพื้นที่เก็บข้อมูลที่ป่องอย่างน่ากลัวเพราะไฟล์ไบนารีใหม่ได้รับการจัดเก็บในทุกการสร้าง หากคุณไม่ได้ใช้งาน Windows ดังที่ระบุไว้ด้านล่าง Annex เป็นโซลูชันที่ดี หากคุณอยู่บน Windows ... จะต้องคอยดูต่อไป
AA Grapsas

4
ปัญหาอีกประการหนึ่งในการมีไฟล์ไบนารีขนาดใหญ่ใน repo คือประสิทธิภาพ Git ไม่ได้ออกแบบมาเพื่อรับมือกับไฟล์ไบนารีขนาดใหญ่และเมื่อขนาด repo เพิ่มขึ้นเป็น 3G + ประสิทธิภาพจะลดลงอย่างรวดเร็ว ซึ่งหมายความว่าการมีไบนารีขนาดใหญ่ใน repo จำกัด ตัวเลือกการโฮสต์ของคุณ
zoul

Submodules สามารถลดความต้องการในการถ่ายโอนข้อมูลเช็คเอาต์ได้หากคุณใช้ submodule ในทางที่ผิด: เมื่อคุณต้องการอัพเดทเนื้อหาของ submodule ให้สร้างคอมมิทใหม่โดยไม่มีพาเรนต์แล้วชี้ superproject (main git repo) ไปที่คอมมิทที่สร้างขึ้นใหม่ เหตุผลนี้สร้างประวัติที่ไม่ได้เชื่อมต่อสำหรับ submodule แต่เป็นการตอบแทนเวอร์ชันของ submodule ใด ๆ ก็สามารถถ่ายโอนได้ง่ายขึ้นเพราะรุ่นนั้นไม่มีประวัติ
Mikko Rantalainen

310

ฉันค้นพบgit-annexเมื่อเร็ว ๆ นี้ซึ่งฉันพบว่ายอดเยี่ยม มันถูกออกแบบมาสำหรับการจัดการไฟล์ขนาดใหญ่ได้อย่างมีประสิทธิภาพ ฉันใช้สำหรับคอลเลกชันภาพถ่าย / เพลง (ฯลฯ ) การพัฒนาของ git-annex นั้นใช้งานได้ดีมาก เนื้อหาของไฟล์สามารถลบออกได้จากที่เก็บ Git เฉพาะลำดับชั้นต้นไม้เท่านั้นที่ถูกติดตามโดย Git (ผ่าน symlink) อย่างไรก็ตามเพื่อให้ได้เนื้อหาของไฟล์จำเป็นต้องมีขั้นตอนที่สองหลังจากดึง / ดันเช่น:

$ git annex add mybigfile
$ git commit -m'add mybigfile'
$ git push myremote
$ git annex copy --to myremote mybigfile ## This command copies the actual content to myremote
$ git annex drop mybigfile ## Remove content from local repo
...
$ git annex get mybigfile ## Retrieve the content
## or to specify the remote from which to get:
$ git annex copy --from myremote mybigfile

มีคำสั่งมากมายและมีเอกสารที่ยอดเยี่ยมบนเว็บไซต์ แพคเกจที่มีอยู่ในDebian


11
โว้ว! โหวตขึ้นสำหรับสุดยอด! ใช้ความคิดที่ฉันมีเมื่อเร็ว ๆ นี้และอีกมากมาย มันเขียนไว้ใน Haskell ไม่น้อย git-media เป็นทางเลือกที่ดี
cdunn2001

33
แต่แอนเน็กซ์ไม่รองรับ Windows ซึ่งเป็นปัญหาสำหรับนักพัฒนาเกม
AA Grapsas

7
ฉันได้ยินมาว่า Steam กำลังลดการรองรับ windows และเพิ่มการรองรับ Linux ... ;) อย่างจริงจังแม้ว่ามันจะยากพอที่จะทำการพอร์ตได้อย่างไร ฉันเดาว่าผู้พัฒนาเกมโดยเฉลี่ยของคุณสามารถทำได้
Sam Watkins

4
@EstebanBrenes ตัวจัดการแจกไพ่ที่แท้จริงคือในการกำหนดค่าปกติ sym Windows ของ Windows ต้องการสิทธิ์ในการสร้าง
Laurens Holst

4
ฉันเพิ่งพบหน้านี้ มันอ่านว่าตอนนี้git annexมีอยู่ในWindowsเช่นกัน หากใครเคยทดสอบใน Windows ฉันอยากได้ยินเกี่ยวกับประสบการณ์ของเขาหรือเธอ!
Kouichi C. Nakamura

49

อีกวิธีหนึ่งนับตั้งแต่เดือนเมษายน 2558 คือGit Large File Storage (LFS) (โดย GitHub)

มันใช้git-lfs (ดูgit-lfs.github.com ) และทดสอบกับเซิร์ฟเวอร์ที่รองรับ: lfs-test-server :
คุณสามารถเก็บข้อมูลเมตาได้เฉพาะใน git repo และไฟล์ขนาดใหญ่อื่น ๆ

https://cloud.githubusercontent.com/assets/1319791/7051226/c4570828-ddf4-11e4-87eb-8fc165e5ece4.gif


3
lfs-test-serverถูกประกาศว่าไม่ใช่สำหรับการใช้งานจริง ที่จริงแล้วฉันกำลังทำงานกับเซิร์ฟเวอร์ LFS ที่ใช้งานจริง ( github.com/artemkin/git-lfs-server ) กำลังดำเนินการ แต่ให้บริการได้แล้วและเรากำลังทดสอบอยู่ในบ้าน
Stas

คุณสามารถเช็คเอาต์ไฟล์ไบนารีรุ่นก่อนหน้านี้โดยใช้ git lfs ได้หรือไม่?
mucaho

1
@mucaho คุณควร: ไวยากรณ์ของ git checkout ไม่เปลี่ยนแปลงและสคริปต์ lfs smudge ควรถูกเรียกใช้
VonC

31

ลองดูgit bupซึ่งเป็นส่วนขยาย Git เพื่อเก็บไบนารีขนาดใหญ่อย่างชาญฉลาดในที่เก็บ Git

คุณต้องการที่จะให้มันเป็น submodule แต่คุณไม่ต้องกังวลเกี่ยวกับที่เก็บยากที่จะจัดการ กรณีการใช้งานตัวอย่างอย่างใดอย่างหนึ่งคือการเก็บอิมเมจ VM ใน Git

ฉันไม่ได้เห็นอัตราการบีบอัดที่ดีขึ้น แต่ที่เก็บของฉันไม่มีไบนารีขนาดใหญ่จริงๆ

ไมล์สะสมของคุณอาจแตกต่างกันไป


3
bup ให้การจัดเก็บ (ภายในใช้คลังเก็บพาริตี้สำหรับความซ้ำซ้อนและคอมไพล์สำหรับการบีบอัด, การลบข้อมูลซ้ำซ้อนและประวัติ) แต่มันไม่ได้ขยาย git Git-ภาคผนวกเป็นส่วนขยายของคอมไพล์ที่ให้แบ็กเอนด์จัดเก็บ BUP
Tobu

@Tobu เมื่อผมโพสต์นี้ภาคผนวกคอมไพล์ไม่ได้ยังมีอยู่ (ในรุ่นหลัก)
sehe

2
bup น่าสนใจมากสำหรับการจัดการไฟล์ขนาดใหญ่ ฉันต้องการจะชี้ให้เห็นความแตกต่างใน UI: คุณใช้คำสั่ง bup นอกบริบทที่เก็บใด ๆ และ git คือรายละเอียดการใช้งาน
Tobu

27

คุณสามารถใช้git-fatได้เช่นกัน ฉันชอบที่มันมี rsyncแต่จะขึ้นอยู่กับหุ้นและงูหลาม นอกจากนี้ยังรองรับเวิร์กโฟลว์ Git ปกติด้วยคำสั่งอธิบายตนเองดังต่อไปนี้:

git fat init
git fat push
git fat pull

นอกจากนี้คุณต้องตรวจสอบไฟล์. gitfat ในพื้นที่เก็บข้อมูลของคุณและแก้ไข. gitattributes ของคุณเพื่อระบุนามสกุลไฟล์ที่คุณต้องการ git fatจัดการ

คุณเพิ่มไบนารีโดยใช้ปกติgit addซึ่งจะเรียกใช้git fatตามกฎ gitattributes ของคุณ

ในที่สุดมันก็มีข้อดีที่ตำแหน่งที่เก็บไบนารีของคุณจริงสามารถใช้ร่วมกันข้ามที่เก็บและผู้ใช้และสนับสนุนสิ่งที่rsyncทำ

อัปเดต: อย่าใช้ git-fat หากคุณใช้สะพาน Git-SVN มันจะจบลงด้วยการลบไฟล์ไบนารีออกจากที่เก็บ Subversion ของคุณ อย่างไรก็ตามหากคุณใช้ที่เก็บ Git ล้วนๆมันทำงานได้อย่างสวยงาม


26

ฉันจะใช้ submodules (เป็น Pat Notz) หรือสอง repositories ที่แตกต่างกัน หากคุณแก้ไขไฟล์ไบนารีบ่อยเกินไปฉันจะพยายามลดผลกระทบของที่เก็บขนาดใหญ่ที่ล้างประวัติ:

ฉันมีปัญหาที่คล้ายกันมากเมื่อหลายเดือนที่ผ่านมา: ไฟล์ MP3 21 GB, ไม่ได้รับการจำแนกประเภท (ชื่อไม่ดี, id3 ที่ไม่ดีไม่ทราบว่าฉันชอบไฟล์ MP3 นั้นหรือไม่ ... ) และทำซ้ำในคอมพิวเตอร์สามเครื่อง

ฉันใช้ฮาร์ดดิสก์ไดรฟ์ภายนอกกับแหล่งเก็บข้อมูลหลักของ Git และฉันโคลนมันลงในคอมพิวเตอร์แต่ละเครื่อง จากนั้นฉันก็เริ่มแบ่งพวกมันออกเป็นนิสัย (ผลัก, ดึง, รวมเข้าด้วยกัน ... ลบและเปลี่ยนชื่อหลาย ๆ ครั้ง)

ในตอนท้ายฉันมีไฟล์ MP3 เพียง ~ 6 GB และ ~ 83 GB ในไดเรกทอรี. git ฉันใช้git-write-treeและgit-commit-treeสร้างคอมมิชชันใหม่โดยไม่ต้องคอมมิชชันบรรพบุรุษและเริ่มสาขาใหม่ที่ชี้ไปที่การคอมมิชชันนั้น "บันทึกคอมไพล์" สำหรับสาขานั้นแสดงการคอมมิชชันเดียวเท่านั้น

จากนั้นฉันลบสาขาเก่าเก็บเฉพาะสาขาใหม่ลบบันทึกอ้างอิงและเรียกใช้ "git prune": หลังจากนั้นโฟลเดอร์. git ของฉันมีน้ำหนักเพียง ~ 6 GB ...

คุณสามารถ "ล้าง" พื้นที่เก็บข้อมูลขนาดใหญ่เป็นครั้งคราวในลักษณะเดียวกัน: "git clone" ของคุณจะเร็วขึ้น


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

1
สิ่งนี้จะเหมือนกันเพียงแค่: rm ​​-f .git; git init; คอมไพล์เพิ่ม ; คอมไพล์ยอมรับ -m "ทิ้งประวัติ"
Pat Notz

1
ใช่มันเหมือนกันในกรณี mp3 ของฉันเท่านั้น แต่บางครั้งคุณไม่ต้องการสัมผัสสาขาและแท็กของคุณ (ไม่มีการลดพื้นที่ในที่เก็บสาธารณะ) แต่คุณต้องการเร่ง "git clone / fetch / pull" ของสาขาเพียงแห่งเดียว ที่เก็บสาขา)
Daniel Fanjul

13

โซลูชันที่ฉันต้องการนำเสนอขึ้นอยู่กับสาขาของเด็กกำพร้าและการใช้กลไกแท็กในทางที่ผิดซึ่งต่อไปนี้จะเรียกว่า * Orphan Tags Binary Storage (OTABS)

TL; DR 12-01-2017หากคุณสามารถใช้ LFS ของ GitHub หรือบุคคลที่สามอื่น ๆ ได้ทุกอย่างควรจะเป็น ถ้าคุณทำไม่ได้อ่านต่อ ได้รับคำเตือนทางออกนี้เป็นแฮ็คและควรได้รับการปฏิบัติเช่นนี้

คุณสมบัติที่พึงประสงค์ของ OTABS

  • มันเป็นคอมไพล์และคอมไพล์เท่านั้นการแก้ปัญหา - มันได้รับงานทำโดยไม่ใช้ซอฟต์แวร์ของบุคคลที่ 3 (ชอบ Git-ภาคผนวก) หรือโครงสร้างพื้นฐานของบุคคลที่ 3 (ชอบ GitHub ของ LFS)
  • มันจัดเก็บไฟล์ไบนารีอย่างมีประสิทธิภาพนั่นคือมันจะไม่ขยายประวัติของที่เก็บของคุณ
  • git pullและgit fetchรวมถึงgit fetch --allยังคงมีแบนด์วิดท์ที่มีประสิทธิภาพนั่นคือไม่ได้ดึงไบนารีขนาดใหญ่ทั้งหมดจากระยะไกลโดยค่าเริ่มต้น
  • การทำงานบนวินโดวส์
  • จะเก็บทุกอย่างในเก็บคอมไพล์เดียว
  • จะช่วยให้การลบไบนารีที่ล้าสมัย (ไม่เหมือน bup)

คุณสมบัติที่ไม่พึงประสงค์ของ OTABS

  • มันgit cloneอาจทำให้ไม่มีประสิทธิภาพ (แต่ไม่จำเป็นขึ้นอยู่กับการใช้งานของคุณ) หากคุณปรับใช้วิธีนี้คุณอาจจะต้องให้คำแนะนำเพื่อนร่วมงานของคุณเพื่อใช้แทนgit clone -b master --single-branch <url> git cloneนี่เป็นเพราะ git clone โดยค่าเริ่มต้นจะทำการโคลนพื้นที่เก็บข้อมูลทั้งหมดรวมถึงสิ่งที่คุณไม่ต้องการเสียแบนด์วิดท์เหมือนปกติ ที่นำมาจากSO 4811434
  • มันทำให้git fetch <remote> --tagsแบนด์วิดธ์ที่ไม่มีประสิทธิภาพ แต่ไม่จำเป็นต้องเก็บข้อมูลไม่มีประสิทธิภาพ คุณสามารถแนะนำเพื่อนร่วมงานของคุณไม่ให้ใช้
  • คุณจะต้องใช้git gcเคล็ดลับในการทำความสะอาดพื้นที่เก็บข้อมูลของคุณจากไฟล์ใด ๆ ที่คุณไม่ต้องการอีกต่อไป
  • มันไม่ได้เป็นที่มีประสิทธิภาพBUPหรือGit-bigfiles แต่มันก็เหมาะสมกว่าสำหรับสิ่งที่คุณพยายามจะทำและยิ่งเพิ่มมากขึ้น คุณมีแนวโน้มที่จะประสบปัญหากับไฟล์ขนาดเล็กหลายแสนไฟล์หรือไฟล์ในช่วงกิกะไบต์ แต่อ่านเพื่อแก้ไขปัญหา

การเพิ่มไฟล์ไบนารี

ก่อนที่คุณจะเริ่มตรวจสอบให้แน่ใจว่าคุณได้ยืนยันการเปลี่ยนแปลงทั้งหมดของคุณแผนภูมิการทำงานของคุณเป็นรุ่นล่าสุดและดัชนีของคุณไม่มีการเปลี่ยนแปลงใด ๆ มันอาจจะเป็นความคิดที่ดีที่จะผลักดันสาขาของคุณทั้งหมดไปยังรีโมต (GitHub ฯลฯ ) ในกรณีที่เกิดภัยพิบัติ

  1. สร้างสาขาใหม่ของเด็กกำพร้า git checkout --orphan binaryStuffจะทำเคล็ดลับ สิ่งนี้จะสร้างสาขาที่ถูกตัดการเชื่อมต่อจากสาขาอื่นอย่างสิ้นเชิงและสิ่งแรกที่คุณจะทำในสาขานี้จะไม่มีพาเรนต์ซึ่งจะทำให้รูทคอมมิท
  2. git rm --cached * .gitignoreทำความสะอาดของคุณโดยใช้ดัชนี
  3. หายใจลึก ๆ rm -fr * .gitignoreและลบต้นไม้ทำงานทั้งหมดโดยใช้ .gitไดเรกทอรีภายในจะไม่ถูกแตะต้องเพราะ*ไวด์การ์ดไม่ตรงกัน
  4. คัดลอกใน VeryBigBinary.exe ของคุณหรือ VeryHeavyDirectory /
  5. เพิ่ม & & กระทำมัน
  6. ตอนนี้มันกลายเป็นเรื่องยาก - ถ้าคุณผลักมันไปที่รีโมตในฐานะสาขานักพัฒนาซอฟต์แวร์ของคุณจะดาวน์โหลดในครั้งต่อไปที่พวกเขาเรียกใช้git fetchการเชื่อมต่อของพวกเขา คุณสามารถหลีกเลี่ยงสิ่งนี้ได้ด้วยการกดแท็กแทนสาขา สิ่งนี้ยังคงส่งผลกระทบต่อแบนด์วิดท์และพื้นที่จัดเก็บระบบไฟล์ของเพื่อนร่วมงานของคุณหากพวกเขามีนิสัยในการพิมพ์git fetch <remote> --tagsแต่อ่านเพื่อหาวิธีแก้ปัญหา ไปข้างหน้าและgit tag 1.0.0bin
  7. git push <remote> 1.0.0binกดแท็กเด็กกำพร้าของคุณ
  8. git branch -D binaryStuffเพียงเพื่อให้คุณไม่เคยผลักดันสาขาไบนารีของคุณโดยบังเอิญคุณสามารถลบได้ ความมุ่งมั่นของคุณจะไม่ถูกทำเครื่องหมายสำหรับการรวบรวมขยะเนื่องจากแท็กเด็กกำพร้าที่ชี้ไปที่มัน1.0.0binเพียงพอที่จะทำให้มันมีชีวิตอยู่

ตรวจสอบไฟล์ไบนารี

  1. ฉัน (หรือเพื่อนร่วมงาน) จะได้รับเช็ค VeryBigBinary.exe จากแผนผังการทำงานปัจจุบันได้อย่างไร git checkout 1.0.0bin -- VeryBigBinary.exeหากสาขาการทำงานปัจจุบันของคุณเป็นตัวอย่างต้นแบบที่คุณสามารถเพียง
  2. สิ่งนี้จะล้มเหลวหากคุณไม่ได้1.0.0binดาวน์โหลดแท็กเด็กกำพร้าซึ่งในกรณีนี้คุณต้องทำgit fetch <remote> 1.0.0binก่อน
  3. คุณสามารถเพิ่มสิ่งเหล่านี้VeryBigBinary.exeลงในปรมาจารย์ของ.gitignoreคุณเพื่อให้ไม่มีใครในทีมของคุณที่จะสร้างมลพิษประวัติศาสตร์หลักของโครงการด้วยไบนารีโดยไม่ได้ตั้งใจ

การลบไฟล์ไบนารีโดยสมบูรณ์

หากคุณตัดสินใจที่จะลบ VeryBigBinary.exe จากที่เก็บในเครื่องของคุณอย่างสมบูรณ์ที่เก็บระยะไกลของคุณและที่เก็บของเพื่อนร่วมงานคุณสามารถ:

  1. ลบแท็กเด็กกำพร้าบนรีโมท git push <remote> :refs/tags/1.0.0bin
  2. ลบแท็กเด็กกำพร้าในประเทศ (ลบแท็ก unreferenced อื่น ๆ git tag -l | xargs git tag -d && git fetch --tagsทั้งหมด) นำมาจากSO 1841341โดยมีการดัดแปลงเล็กน้อย
  3. ใช้เคล็ดลับ git gc เพื่อลบการกระทำที่ไม่ได้รับการอ้างอิงในขณะนี้ของคุณ git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "$@". มันจะลบการกระทำที่ไม่ได้อ้างถึงอื่น ๆ ทั้งหมด นำมาจากSO 1904860
  4. หากเป็นไปได้ให้ทำซ้ำเคล็ดลับ git gc บนรีโมท เป็นไปได้ถ้าคุณจัดการพื้นที่เก็บข้อมูลด้วยตนเองและอาจไม่สามารถทำได้กับผู้ให้บริการบางรายเช่น github หรือในสภาพแวดล้อมขององค์กร หากคุณกำลังโฮสต์กับผู้ให้บริการที่ไม่ให้สิทธิ์การเข้าถึงรีโมตแก่คุณ เป็นไปได้ว่าโครงสร้างพื้นฐานของผู้ให้บริการของคุณจะทำความสะอาดความมุ่งมั่นที่ไม่ได้อ้างถึงในช่วงเวลาที่แสนหวาน หากคุณอยู่ในสภาพแวดล้อมขององค์กรคุณสามารถให้คำปรึกษาด้านไอทีของคุณในการเรียกใช้งานขยะ cron รวบรวมระยะไกลของคุณหนึ่งครั้งต่อสัปดาห์หรือมากกว่านั้น ไม่ว่าจะทำหรือไม่จะไม่มีผลกระทบใด ๆ ในทีมของคุณในแง่ของแบนด์วิดธ์และการเก็บรักษานานเท่าที่คุณแนะนำให้เพื่อนร่วมงานของคุณเสมอแทนgit clone -b master --single-branch <url>git clone
  5. เพื่อนร่วมงานทุกคนของคุณที่ต้องการกำจัดแท็กเด็กกำพร้าที่ล้าสมัยต้องใช้ขั้นตอนที่ 2-3 เท่านั้น
  6. จากนั้นคุณสามารถทำซ้ำขั้นตอนที่ 1-8 ของการเพิ่มไฟล์ไบนารี2.0.0binสร้างแท็กใหม่เด็กกำพร้า หากคุณกำลังกังวลเกี่ยวกับเพื่อนร่วมงานของคุณพิมพ์คุณจริงสามารถตั้งชื่อมันอีกครั้งgit fetch <remote> --tags 1.0.0binสิ่งนี้จะทำให้แน่ใจว่าครั้งต่อไปที่พวกเขาดึงแท็กทั้งหมดที่เก่า1.0.0binจะไม่ได้รับการยืนยันและทำเครื่องหมายสำหรับการรวบรวมขยะในภายหลัง (ใช้ขั้นตอนที่ 3) เมื่อคุณพยายามที่จะเขียนทับแท็กบนรีโมทคุณต้องใช้-fสิ่งนี้:git push -f <remote> <tagname>

เล่ม

  • OTABS ไม่ได้สัมผัสต้นแบบของคุณหรือรหัสต้นฉบับ / สาขาการพัฒนาอื่น ๆ แฮชการคอมมิชชันประวัติทั้งหมดและขนาดที่เล็กของสาขาเหล่านี้จะไม่ได้รับผลกระทบ หากคุณเปิดเผยประวัติซอร์สโค้ดของคุณด้วยไฟล์ไบนารีคุณจะต้องล้างมันให้เป็นงานแยกต่างหาก สคริปต์นี้อาจมีประโยชน์

  • ได้รับการยืนยันให้ทำงานบน Windows ด้วย git-bash

  • มันเป็นความคิดที่ดีที่จะใช้ ชุดของ trics มาตรฐานเพื่อให้การจัดเก็บไฟล์ไบนารีมีประสิทธิภาพมากขึ้น การใช้งานบ่อยครั้งgit gc(โดยไม่มีข้อโต้แย้งเพิ่มเติม) ทำให้ git เพิ่มประสิทธิภาพการจัดเก็บข้อมูลพื้นฐานของไฟล์ของคุณโดยใช้ไบนารีเดลต้า อย่างไรก็ตามหากไฟล์ของคุณไม่น่าจะคล้ายกันจากการคอมมิทถึงการคอมมิทคุณสามารถปิดเดลตาไบนารีได้ทั้งหมด นอกจากนี้เนื่องจากไม่สามารถบีบอัดไฟล์ที่ถูกบีบอัดหรือเข้ารหัสได้แล้วเช่น. zip, .jpg หรือ. crypt ดังนั้น git จึงช่วยให้คุณสามารถปิดการบีบอัดหน่วยความจำพื้นฐานได้ น่าเสียดายที่การตั้งค่าทั้งหมดหรือไม่มีอะไรส่งผลกระทบต่อซอร์สโค้ดของคุณเช่นกัน

  • คุณอาจต้องการสคริปอัพบางส่วนของ OTABS เพื่อให้สามารถใช้งานได้เร็วขึ้น โดยเฉพาะอย่างยิ่งการเขียนสคริปต์ขั้นตอน 2-3 จากลบไฟล์ไบนารีทั้งหมดลงในupdateตะขอคอมไพล์สามารถให้ความหมายที่น่าสนใจ แต่อาจเป็นอันตรายถึงความหมายในการเรียก git ("ดึงและลบทุกอย่างที่ล้าสมัย")

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

  • ในโลก Java เป็นไปได้ที่จะรวมโซลูชันนี้เข้าด้วยกัน maven --offlineเพื่อสร้างบิลด์ออฟไลน์ที่ทำซ้ำได้ซึ่งถูกจัดเก็บไว้ในการควบคุมเวอร์ชันของคุณ ใน golang โลกจะเป็นไปได้ที่จะสร้างในการแก้ปัญหานี้เพื่อจัดการ GOPATH go getของคุณแทน ในโลกหลามมันเป็นไปได้ที่จะรวมสิ่งนี้เข้ากับ virtualenv เพื่อสร้างสภาพแวดล้อมการพัฒนาที่มีในตัวเองโดยไม่ต้องพึ่งพาเซิร์ฟเวอร์ PyPi สำหรับทุกการสร้างตั้งแต่เริ่มต้น

  • หากไฟล์ไบนารีของคุณเปลี่ยนแปลงบ่อยเช่นการสร้างสิ่งประดิษฐ์ที่มันอาจจะเป็นความคิดที่ดีในการแก้ปัญหาสคริปต์ที่ร้านค้า 5 รุ่นล่าสุดของสิ่งประดิษฐ์ในแท็กเด็กกำพร้าmonday_bin, tuesday_bin, ... , friday_binและยังมีแท็กเด็กกำพร้าสำหรับแต่ละรุ่น1.7.8bin 2.0.0binฯลฯ คุณสามารถหมุนweekday_binและลบไบนารีเก่าได้ทุกวัน วิธีนี้จะทำให้คุณได้รับสองโลกที่ดีที่สุด: คุณเก็บประวัติทั้งหมดของซอร์สโค้ดของคุณ แต่จะมีเพียงประวัติที่เกี่ยวข้องของการพึ่งพาไบนารีของคุณ นอกจากนี้ยังง่ายมากที่จะได้รับไฟล์ไบนารีสำหรับแท็กที่กำหนดโดยไม่ได้รับซอร์สโค้ดทั้งหมดพร้อมประวัติทั้งหมด: git init && git remote add <name> <url> && git fetch <name> <tag>ควรทำเพื่อคุณ


"คุณต้องใช้งานเป็นระยะgit gc" - หยุดอ่านตรงนั้น ทำไมทุกคนถึงยอมแพ้เข็มขัดนิรภัยครั้งสุดท้ายเพื่อให้แฮ็คบางคน?
user1643723

@ user1643723 git gcไม่ปลอดภัยที่จะเรียกใช้ ความมุ่งมั่นที่ห้อยต่องแต่งทั้งหมดของคุณจะถูกเก็บไว้ในฮาร์ดไดรฟ์อย่างปลอดภัยเป็นเวลาอย่างน้อย 30 วันโดยค่าเริ่มต้น: git-scm.com/docs/git-gc
Adam Kurkiewicz

ขอบคุณสำหรับการเขียนรายละเอียด ฉันต้องการลองใช้วิธีนี้เป็นวิธีในการจัดเก็บการอ้างอิงไบนารีบางอย่างใน repo GitHub ของฉันในลักษณะที่พวกเขาไม่ได้ดาวน์โหลดตามค่าเริ่มต้นเมื่อมีคนโคลน repo แต่สามารถดาวน์โหลดได้ด้วยตนเองและอัพเดท repo ในพื้นที่ แต่ผมมีข้อผิดพลาดในขั้นตอนนี้: -git push <remote> 1.0.0bin remote: error: GH001: Large files detected. You may want to try Git Large File Storageดูเหมือนว่า GitHub จะไม่สนับสนุนสิ่งนี้อีกต่อไปหรือ เลขฐานสองในคำถามคือขนาด 100MB
user5359531

1
หากคุณได้รับอนุญาตให้ใช้ GitHub ในการทำงานของคุณสิ่งที่ทำให้คุณไม่สามารถใช้ LFS ได้ พวกที่ GitHub ทำงานอย่างหนักเพื่อสร้างผลิตภัณฑ์นี้และพวกเขายังจัดการโฮสต์สำหรับคุณและโครงสร้างพื้นฐานของพวกเขาได้รับการปรับให้เหมาะกับการใช้งาน แฮ็คนี้มีไว้สำหรับสถานการณ์ที่คุณไม่สามารถใช้ LFS หรือบุคคลที่สามอื่น ๆ ได้อย่างแท้จริงและคุณกำลังตามหาวิธีแก้ปัญหาแบบคอมไพล์
Adam Kurkiewicz

ฉันได้อัปเดตคำตอบเพื่อให้ชัดเจนยิ่งขึ้นเกี่ยวกับวิธีการแฮ็กโซลูชันนี้จริง ๆ
Adam Kurkiewicz

13

ในความคิดของฉันถ้าคุณมักจะแก้ไขไฟล์ขนาดใหญ่เหล่านั้นหรือถ้าคุณตั้งใจจะทำมากgit cloneหรือgit checkoutอย่างนั้นคุณควรพิจารณาใช้พื้นที่เก็บข้อมูล Git อื่นอย่างจริงจัง (หรืออาจเป็นวิธีอื่นในการเข้าถึงไฟล์เหล่านั้น)

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


13
และ repos แยกกันจะไม่ทำให้เวลาชำระเงินสั้นลงเนื่องจากคุณยังต้องตรวจสอบ repos ทั้งสอง!
Emil Sit

@EmilSit repo แยกกันทำให้การเช็คเอาต์สั้นลงถ้าคุณล้างประวัติของ "repo binary" อย่างต่อเนื่อง devs นอกจากจะไม่ถูกบังคับให้ชำระเงินทั้ง Repos ในแต่ละครั้ง
FabienAndre

ทำไมไม่ให้สคริปต์สร้างของโมดูลหลักดึงไฟล์ไบนารีจาก repo ตัวที่สองแยกมันทีละรายการ (เช่นที่นี่: stackoverflow.com/questions/1125476/ … )
akauppi

1
แม้ว่าไฟล์ไบนารีของคุณจะไม่เปลี่ยนแปลงบ่อยครั้ง แต่ไฟล์ขนาดใหญ่ยังคงสามารถฆ่าเวิร์กโฟลว์ของคุณได้หากคุณมักจะผลักสาขาไปยังที่เก็บเพื่อการทำงานร่วมกัน
Timo Reimann

9

SVN ดูเหมือนว่าจะจัดการกับ delta แบบไบนารีอย่างมีประสิทธิภาพมากกว่า Git

ฉันต้องตัดสินใจเกี่ยวกับระบบการกำหนดเวอร์ชันสำหรับเอกสารประกอบ (ไฟล์ JPEG, ไฟล์ PDF และไฟล์. odt) ฉันเพิ่งทดสอบการเพิ่มไฟล์ JPEG และหมุน 90 องศาสี่ครั้ง (เพื่อตรวจสอบประสิทธิภาพของเดลต้าไบนารี) พื้นที่เก็บข้อมูลของ Git เพิ่มขึ้น 400% พื้นที่เก็บข้อมูลของ SVN เพิ่มขึ้นเพียง 11%

ดังนั้นดูเหมือนว่า SVN จะมีประสิทธิภาพมากขึ้นกับไฟล์ไบนารี

ดังนั้นตัวเลือกของฉันคือ Git สำหรับซอร์สโค้ดและ SVN สำหรับไฟล์ไบนารีเช่นเอกสาร


33
คุณเพียงแค่ต้องเรียกใช้ "git gc" (การแบ่งบรรจุและการรวบรวมขยะ) หลังจากเพิ่มไฟล์เหล่านั้น 4 ไฟล์ Git ไม่ได้บีบอัดเนื้อหาที่เพิ่มทั้งหมดทันทีดังนั้นคุณจะมีการบีบอัดแบบกลุ่มของไฟล์ (ซึ่งมีประสิทธิภาพมากขึ้นในแง่ของขนาด) และจะไม่มีการชะลอตัวของการบีบอัดแยกต่างหากทุกวัตถุที่เพิ่มเข้ามาที่นั่น แต่ถึงแม้จะไม่มี "git gc" แต่ git ก็จะทำการบีบอัดข้อมูลให้คุณในที่สุด (หลังจากที่สังเกตเห็นว่ามีวัตถุที่ยังไม่ได้แพ็คพอสะสม)
ไนติงเกล

24
@jpierson ฉันสร้างพื้นที่เก็บข้อมูล git ที่ว่างเปล่าและเพิ่ม (และมุ่งมั่น) อิมเมจ bmp สีขาวทั้งหมดที่มีขนาด 41MB ซึ่งทำให้พื้นที่เก็บข้อมูล git ทั้งหมดมีขนาด 328KB หลังจากgit gcขนาดพื้นที่เก็บข้อมูล git รวมลดลงเหลือ 184KB จากนั้นฉันเปลี่ยนพิกเซลเดียวจากสีขาวเป็นสีดำและยืนยันการเปลี่ยนแปลงนี้ขนาดพื้นที่เก็บข้อมูล git รวมเพิ่มขึ้นเป็น 388KB และหลังจากgit gcขนาดของพื้นที่เก็บข้อมูล git ทั้งหมดลดลงเป็น 184KB นี่แสดงให้เห็นว่าคอมไพล์ค่อนข้างดีในการบีบอัดและค้นหาเดลต้าของไฟล์ไบนารี
Tader

6
@ jpierson A sidenote: ฉันเพิ่งแสดงความคิดเห็นในฐานสามเหลี่ยม Git จะกินหน่วยความจำของคุณทั้งหมดและสลับถ้ามันจัดการที่เก็บด้วยไฟล์ขนาดใหญ่ (GB ขนาด) สำหรับเรื่องนี้ใช้git-ภาคผนวก (ดังกล่าวแล้วในคำตอบอื่น ๆ ) ...
Tader

12
@JanDvorak - ไม่มีใครพูดถึงมันเพราะมันไม่จริงอย่างสมบูรณ์ สำเนาการโค่นล้มมีราคาถูก - svnbook.red-bean.com/en/1.7/svn.branchmerge.using.html - ประมาณกลางหน้า
Joris Timmermans

12
@Tader: การทดสอบของคุณไม่ดี สิ่งที่คุณเรียกไฟล์ไบนารี่คือความจริง (จากมุมมองของคอมไพล์) มากกว่าไฟล์ข้อความ - บิตสตรีมจะถูกจัดเรียงเป็นไบต์และมีความแตกต่างที่มีความหมายแปลเป็นภาษาท้องถิ่น ท้ายที่สุดแล้วการเปลี่ยนหนึ่งพิกเซลนั้นเทียบเท่ากับการเปลี่ยนอักขระหนึ่งตัวในไฟล์ข้อความ (และใครเป็นผู้ใช้บิตแมปที่ไม่มีการบีบอัดในปัจจุบัน?) ลองใช้การทดลองเดียวกันกับวิดีโอขนาดเล็กภาพบีบอัดเครื่องเสมือนไฟล์ zip หรืออะไรก็ตาม คอมไพล์นั้นไม่สามารถจัดการกับเดลต้าได้อย่างมีประสิทธิภาพ แน่นอนมันเป็นไปไม่ได้โดยพื้นฐานกับข้อมูลที่บีบอัดไม่ได้
Eamon Nerbonne

4

git clone --filter จาก Git 2.19 + โคลนนิ่งตื้น

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

อนุญาตให้เรียกไฟล์และไดเรกทอรีที่คุณต้องการสำหรับเซิร์ฟเวอร์เท่านั้นและได้รับการแนะนำพร้อมกับส่วนขยายโปรโตคอลระยะไกล

ด้วยสิ่งนี้เราสามารถโคลนโคลนได้ก่อนจากนั้นจึงทำให้ blobs ที่ดึงข้อมูลด้วยระบบการสร้างสำหรับบิลด์แต่ละประเภทโดยอัตโนมัติ

แม้จะมีอยู่แล้ว --filter=blob:limit<size>ซึ่งช่วยให้การ จำกัด ขนาดหยดสูงสุดที่จะดึง

ฉันได้ให้ตัวอย่างที่มีรายละเอียดน้อยที่สุดเกี่ยวกับลักษณะที่ปรากฏของ: ฉันจะโคลนไดเรกทอรีย่อยของที่เก็บ Git ได้อย่างไร


2

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

ผมเองยังวิ่งเข้ามาในความล้มเหลวของการประสานกับ Gitกับบางส่วนของเจ้าภาพเมฆของฉันเมื่อใช้งานเว็บข้อมูลไบนารีของฉันมีรอยบากข้างต้นเครื่องหมาย 3 GB ฉันพิจารณาBFT Repo Cleanerในเวลานั้น แต่มันรู้สึกเหมือนแฮ็ค ตั้งแต่นั้นมาฉันเริ่มเก็บไฟล์ไว้นอกขอบเขตของ Git แทนที่จะใช้ประโยชน์จากเครื่องมือที่สร้างขึ้นเองเช่น Amazon S3 สำหรับจัดการไฟล์การกำหนดเวอร์ชันและการสำรองข้อมูล

ใครบ้างมีประสบการณ์กับที่เก็บ Git หลายแห่งและจัดการมันในโครงการเดียว

ใช่. ธีมของ Hugoได้รับการจัดการด้วยวิธีนี้เป็นหลัก มันเป็นความดุดันเล็กน้อย แต่ก็ทำให้งานเสร็จ


ข้อเสนอแนะของฉันคือการเลือกเครื่องมือที่เหมาะสมสำหรับงาน ถ้าเป็นของ บริษัท และคุณกำลังจัดการ codeline ของคุณใน GitHub จ่ายเงินและใช้ Git-LFS มิฉะนั้นคุณสามารถสำรวจตัวเลือกที่สร้างสรรค์มากขึ้นเช่นการจัดเก็บไฟล์ที่เข้ารหัสแบบกระจายโดยใช้ blockchainblockchain

ตัวเลือกเพิ่มเติมในการพิจารณารวมถึงMinioและs3cmd


0

มีลักษณะที่camlistore มันไม่ได้ใช้ Git แต่ฉันคิดว่ามันเหมาะสมกว่าสำหรับสิ่งที่คุณต้องทำ

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