จะลบวัตถุที่ไม่ได้ใช้ออกจากที่เก็บ git ได้อย่างไร?


90

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

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

แก้ไข : ขอบคุณสำหรับคำตอบ; ฉันลองวิธีแก้ปัญหาหลายอย่าง ไม่มีผล ตัวอย่างเช่นไฟล์จาก GitHub ลบไฟล์ออกจากประวัติ แต่.gitขนาดไดเร็กทอรีไม่ลดลง:

$ BADFILES=$(find test_data -type f -exec echo -n "'{}' " \;)

$ git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $BADFILES" HEAD
Rewrite 14ed3f41474f0a2f624a440e5a106c2768edb67b (66/66)
rm 'test_data/images/001.jpg'
[...snip...]
rm 'test_data/images/281.jpg'
Ref 'refs/heads/master' was rewritten

$ git log -p # looks nice

$ rm -rf .git/refs/original/
$ git reflog expire --all
$ git gc --aggressive --prune
Counting objects: 625, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (598/598), done.
Writing objects: 100% (625/625), done.
Total 625 (delta 351), reused 0 (delta 0)

$ du -hs .git
174M    .git
$ # still 175 MB :-(

13
เป็นเพียงคำเตือนสำหรับโมเดอเรเตอร์คำถามนี้ 100% เป็นของ SO ไม่ใช่ superuser
VonC


ตามที่กล่าวไว้ที่นี่ ( stackoverflow.com/questions/685319/… ) คุณได้ลองรีแพ็กหลังจาก gc ของคุณหรือไม่ git-repack -aตามด้วยgit-prune-packedเช่น ดูblog.felipebalbi.com/2007/12/19/…
VonC

2
@ โจนาส: แล้วถ้าหลังจากที่คุณทำทั้งหมดนั้นคุณจะโคลน repo ของคุณล่ะ? คุณต้องการจากนั้นได้รับการโคลนที่มีขนาดลดลงตามที่ต้องการหรือไม่?
VonC

1
@Jonas: หลังจากที่ทุกสิ่งที่คุณทำ ( filter-branch, gc, repack, ... ) ไม่มีคุณไม่ควรดูไม่ดีใด ๆ ที่กระทำการที่ทุกคน นี่เป็นสัญญาณว่าการทำความสะอาดไม่ได้เกิดขึ้นอย่างที่คิด
VonC

คำตอบ:


129

ฉันตอบสิ่งนี้ที่อื่นและจะคัดลอกที่นี่เพราะฉันภูมิใจ!

... และโดยไม่ต้องกังวลใจอีกต่อไปฉันขอนำเสนอสคริปต์ที่มีประโยชน์นี้กับคุณ git-gc-all รับประกันว่าจะลบขยะคอมไพล์ทั้งหมดของคุณจนกว่าพวกเขาอาจมีตัวแปรกำหนดค่าเพิ่มเติม:

git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 \
  -c gc.rerereresolved=0 -c gc.rerereunresolved=0 \
  -c gc.pruneExpire=now gc "$@"

ตัวเลือก --aggressive อาจมีประโยชน์

หมายเหตุ: สิ่งนี้จะลบสิ่งที่ไม่ได้อ้างอิงทั้งหมดดังนั้นอย่ามาร้องไห้กับฉันหากคุณตัดสินใจในภายหลังว่าคุณต้องการเก็บสิ่งเหล่านี้ไว้!

คุณอาจต้องเรียกใช้สิ่งเหล่านี้ก่อนโอ้ที่รักคอมไพล์ซับซ้อน !!

git remote rm origin
rm -rf .git/refs/original/ .git/refs/remotes/ .git/*_HEAD .git/logs/
git for-each-ref --format="%(refname)" refs/original/ |
  xargs -n1 --no-run-if-empty git update-ref -d

ฉันใส่ทั้งหมดนี้ไว้ในสคริปต์ที่นี่:

http://sam.nipl.net/b/git-gc-all-ferocious


เช่นเดียวกับในstackoverflow.com/questions/1904860/… , +1 ให้คุณอีกครั้ง
VonC

18
ยอดเยี่ยม: D แผนชั่วร้ายของฉันที่จะได้รับคะแนนมากขึ้นโดยการโคลนนิ่งคำตอบได้ผล !! 1;)
Sam Watkins

ใช่ สิ่งนี้ได้ผล แต่ฉันต้องเรียกใช้สคริปต์ทั้งหมด การรันเฉพาะคำสั่ง gc (พร้อมตัวเลือก config) นั้นไม่เพียงพอ
Daniel

4
102m ถึง 160k .. มีประสิทธิภาพและทำลายล้าง
prusswan

4
ขอบคุณมากสำหรับสคริปต์! ข้อมูลโบนัส: xargsคำสั่งสร้างข้อผิดพลาดบน OS X เนื่องจากตัวเลือกที่ไม่รู้จัก ทางออกที่ง่ายที่สุด: ติดตั้ง xargs GNU ผ่าน homebrew brew install findutilsและแทนที่โดยxargs gxargs
qqilihq

26

ของคุณgit reflog expire --allไม่ถูกต้อง ลบรายการ reflog ที่เก่ากว่าเวลาหมดอายุซึ่งมีค่าเริ่มต้นเป็น 90 วัน ใช้git reflog expire --all --expire=now.

คำตอบของฉันสำหรับคำถามที่คล้ายกันเกี่ยวข้องกับปัญหาการขัดวัตถุที่ไม่ได้ใช้ออกจากที่เก็บข้อมูล


18

1) ลบไฟล์ออกจาก git repo (& ไม่ใช่ระบบไฟล์):

  • git rm --cached path/to/file

2) ลดขนาด repo โดยใช้:

  • git gc,

  • หรือ git gc --aggressive

  • หรือ git prune

หรือการรวมกันของข้างต้นตามที่แนะนำในคำถามนี้: ลดขนาดที่เก็บ git


10

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

หากคุณต้องการให้ไบนารีพร้อมใช้งานใน repo สำหรับบุคคลอื่นไม่มีทางที่จะทำสิ่งที่คุณต้องการได้อย่างแท้จริง มันค่อนข้างทั้งหมดหรือไม่มีเลย


8

กุญแจสำคัญสำหรับฉันกลายเป็นว่ากำลังทำงานอยู่git repack -A -d -fแล้วgit gcเพื่อลดขนาดของ git pack เดียวที่ฉันมี


6

เฮ!

Git รับเฉพาะวัตถุที่ต้องการจริงๆเมื่อโคลนที่เก็บ (ถ้าฉันเข้าใจถูกต้อง)

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

จากนั้นเมื่อคุณสร้างโคลนใหม่ของ repo นั้นไดเร็กทอรี. git ควรมีขนาดเล็กเท่ากับไฟล์ขนาดใหญ่ที่คอมมิต

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


5
git filter-branch --index-filter 'git rm --cached --ignore-unmatch Filename' --prune-empty -- --all

อย่าลืมเปลี่ยนFilenameสำหรับสิ่งที่คุณต้องการลบออกจากที่เก็บ



0

ในปี 2020 เอกสารสำหรับคอมไพล์กรองสาขาลดการใช้งานและแนะนำให้ใช้ทางเลือกเช่นGit-กรอง repo นอกจากนี้ยังสามารถนำมาใช้แทนการ BFG

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

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