ฉันจะแก้ไขแผนผังย่อย git ได้อย่างไรหลังจากแรงผลักดันโครงการอัปสตรีมไปยังมาสเตอร์


13

ฉันได้ทดลองกับการใช้ทรีย่อย git และพบกับสถานการณ์ต่อไปนี้

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

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

ฉันจะอัพเดตที่เก็บของฉันเพื่อสะท้อนประวัติศาสตร์ใหม่ของทรีย่อยได้อย่างไร

ความพยายามครั้งแรกของฉันคือการใช้สาขาตัวกรองเพื่อลบทรีย่อยและประวัติทั้งหมดอย่างสมบูรณ์

git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch upstream-project-dir' --prune-empty HEAD

เมื่อลบทรีย่อยเวอร์ชันเก่าออกแล้วฉันสามารถเพิ่มทรีย่อยอีกครั้งโดยใช้ upstream master ใหม่ อย่างไรก็ตามสิ่งนี้ไม่ได้ผลเพราะเหตุผลบางอย่างประวัติการส่งมอบยังคงปรากฏในเอาต์พุตบันทึก git

ปรับปรุง

ฉันเขียนขั้นตอนต่าง ๆ เพื่อสร้างตัวอย่างที่จำลองได้น้อยที่สุด

  1. สร้าง repo git ที่ว่างเปล่าก่อน

    git init test-monorepo
    cd ./test-monorepo
    
  2. สร้างความมุ่งมั่นเริ่มต้น

    echo hello world > README
    git add README
    git commit -m 'initial commit'
    
  3. ตอนนี้เพิ่มทรีย่อยสำหรับโครงการภายนอก

    git remote add thirdparty git@github.com:teivah/algodeck.git
    git fetch thirdparty
    git subtree add --prefix algodeck thirdparty master
    
  4. ให้คำมั่นสัญญากับ monorepo

    echo dont panic >> algodeck/README.md
    git commit -a -m 'test commit'
    
  5. ทีนี้ลองใช้ git filter-branch เพื่อลบทรีย่อย

    git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch algodeck' --prune-empty HEAD
    
  6. ตรวจสอบเอาต์พุตของคอมไพล์ฉันคาดหวังว่าจะเห็นเฉพาะการคอมมิทเริ่มต้นของฉัน

    git log
    

คุณได้ลอง git gc --prune = ตอนนี้เพื่อทิ้งคอมมิชชันเก่าหรือไม่? มีการอ้างอิงถึงเวอร์ชั่นเก่าบ้างไหม?
Damiano

1
ฉันยังไม่ได้ลอง แต่จะไม่git gc --prune=nowลบเฉพาะการกระทำที่ไม่ปรากฏในgit logเท่านั้น
csnate

ใช้สาขา git - ทั้งหมด (ที่ฉันคิดว่าคุณใช้เพื่อดูการกระทำ "เก่า") ควรแสดงความมุ่งมั่นที่ไม่เกี่ยวข้องกับสาขาปัจจุบันของคุณ
Damiano

1
ที่จริงฉันเพิ่งทำgit logไม่มีข้อโต้แย้งและฉันยังเห็นความมุ่งมั่นเก่า
csnate

กรุณาโพสต์บันทึกการคอมไพล์ของคุณ - คำว่า - ทั้งหมด - กราฟ? เพียงเพื่อให้เข้าใจสถานการณ์ของคุณ
Damiano

คำตอบ:


0

คุณมีประวัติไม่ดีอยู่แล้วในประวัติศาสตร์ของคุณและคุณต้องกำจัดมันก่อนที่จะดำเนินการต่อ

สมมติว่าคุณได้รับmasterการเบี่ยงเบนไปจากครั้งล่าสุดและไม่สามารถทำสิ่งอื่นได้อีก (ฉันไม่มีกิ่งที่เห็นดังนั้นฉันต้องสมมติสิ่งที่เริ่มต้นด้วย)

คุณสามารถชำระเงินให้กับการส่งก่อนหน้าและกดเครื่องหมายสาขา 1 ขั้นตอนย้อนกลับ (หรือ X ก้าวถอยหลัง) ซึ่งจะไม่เป็นอันตรายในกรณีใด ๆ แล้วดึงอีกครั้ง

เช่น

git checkout master~1
git branch master -f
git checkout master
git pull
  1. git checkout master~1 เพื่อชำระค่าคอมมิชชันของมาสเตอร์, คอมไพล์เตือนว่าเราปิดสาขา
  2. git branch master -f เพื่อบังคับให้เช็คเอาต์ปัจจุบันกลายเป็นมาสเตอร์อีกครั้งนั่นคือการกรอกลับสาขาหลักเป็นการกระทำก่อนหน้า (หรือการกระทำก่อนหน้า X) และจากที่นี่ไม่สำคัญว่าตอนต้นน้ำบังคับหรือไม่เราสามารถกลับมาทำงานตามปกติหรือแม้กระทั่ง ย้อนกลับไปที่ขั้นตอนด้านบนหากจำเป็นเราสามารถดึงเจ้านายได้อีกครั้งโดยไม่สูญเสียอะไรจากอัปสตรีม (ซึ่งสำหรับเราสามารถอ่านได้อย่างเดียวเช่นกันเราจะไม่ผลักดันสิ่งนี้)
  3. git checkout master ที่จะอยู่ในสาขาหลักของเรา "กรอกลับ" ความมุ่งมั่นแบบเดียวกันกับที่เรากำลังก้าวเข้ามา
  4. git pullที่จะดึงต้นแบบอีกครั้ง (สามารถมีหรือไม่มี--prune) ถ้าเบี่ยงเบนต้นน้ำเราจะกลับไปติดตามจากที่นี่ถ้าไม่เราจะได้เหมือนกันเรามีถ้าเราได้เหมือนกันและไม่ควรบางทีเรา จำเป็นต้องกลับไปที่ขั้นตอนที่ 1 ด้านบนและกรอกลับอีกครั้งเช่นgit checkout master~5หรืออะไรก็ตาม (ตามต้องการ)

ฉันไม่คิดว่านี้จะทำงานร่วมกับgit subtree
csnate

@csnate เป็นไปได้ที่จะชำระค่าคอมมิชชันก่อนหน้านี้จาก subrepo และทำตามขั้นตอนที่คล้ายกันมากถ้าคุณสร้าง MCVE จะเป็นการง่ายกว่าที่จะบอกคุณว่าคำสั่งที่แน่นอนให้ทำตามstackoverflow.com/help/minimal-reproducible-example
arhak

ฉันจะพยายามสร้าง repo ตัวอย่างบน GitHub
csnate

ฉันสร้างชุดของขั้นตอนในคำถามเดิมที่แสดงปัญหา
csnate

0
  1. ใน repo ของคุณให้ล้างประวัติการกระทำของรีโมตนี้:

    git fetch upstream
    
  2. หากหนึ่งในการกระทำของคุณมีการกระทำที่มีไฟล์ขนาดใหญ่ให้เขียนประวัติของคุณใหม่เพื่อไม่ให้มีการอ้างอิงไฟล์ขนาดใหญ่อีกต่อไป

    # using one or more of the following commands :
    git rebase --interactive
    git filter-branch
    ...
    

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


หากคุณมีความจำเป็นเร่งด่วนในการลบไฟล์ขนาดใหญ่นี้โดยเร็วจากฮาร์ดไดรฟ์ของคุณ:

ทำงานด้วยตนเอง

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