ฉันจะย้ายไดเร็กทอรีเดียวจากที่เก็บ git ไปยังที่เก็บใหม่ในขณะที่รักษาประวัติได้อย่างไร


110

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

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


2
เพิ่มแท็ก git-submodules เนื่องจากมีประโยชน์มากสำหรับการแปลงส่วนของ repo เป็นโมดูลย่อย
idbrii

คำตอบ:


99

คุณสามารถใช้git filter-branchเพื่อเขียนประวัติของโครงการใหม่ จากเอกสารประกอบ:

หากต้องการเขียนที่เก็บใหม่ให้ดูเหมือนว่า foodir / เคยเป็นรูทโปรเจ็กต์และทิ้งประวัติอื่น ๆ ทั้งหมด:

git filter-branch --subdirectory-filter foodir -- --all

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


1
จะเป็นอย่างไรหากฉันต้องการยกเว้น foodir และลบประวัติทั้งหมด
saeedgnu

1
หมายเหตุ: หากคุณต้องการหลายไดเรกทอรีคุณจะต้องระบุ--subdirectory-filterหลายครั้ง EG git filter-branch --subdirectory-filter foodir --subdirectory-filter bardirฯลฯ--subdirectoryจะไม่ใช้เวลาหลาย dirs แต่สามารถระบุได้หลายครั้ง
EnabrenTane

3
@Adam หากคุณต้องการเก็บประวัติfoodirไว้ในโปรเจ็กต์เดิมไม่ใช่การเขียนประวัติใหม่ก็git rm -r foodirน่าจะเพียงพอแล้ว (ซึ่งจะลบสำเนาในแผนผังการทำงานของคุณด้วยหากคุณไม่ต้องการให้ใช้--cached) หากคุณต้องการลบทั้งหมดออกจากประวัติ (ตอบคำถามของ @ ilius ด้วย) คุณต้องการอะไรเช่นgit filter-branch --index-filter 'git rm -r --cached --ignore-unmatched foodir' -- --all
Brian Campbell

2
@ilius ขออภัยฉันพลาดคำถามของคุณก่อนหน้านี้โปรดดูคำตอบของฉันด้านบนเพื่อดูคำตอบเกี่ยวกับวิธีลบไดเรกทอรีและประวัติ
Brian Campbell

2
@ilius ใช่นั่นก็ใช้ได้เหมือนกัน สำหรับโปรเจ็กต์ขนาดใหญ่การ--index-filterแก้ปัญหานั้นเร็วกว่า--tree-filterเนื่องจากไม่ต้องตรวจสอบไฟล์จริงๆจึงสามารถจัดการกับดัชนีได้โดยตรง อย่างไรก็ตาม--tree-filterสามารถใช้งานได้ง่ายขึ้นเล็กน้อยเนื่องจากคุณสามารถใช้การดำเนินการระบบฟิลส์ทั่วไปแทนที่จะต้องทำงานกับการดำเนินการจัดการดัชนี
Brian Campbell

4

ในการส่งออกโฟลเดอร์เป็นที่เก็บใหม่คุณต้อง:

  1. เพื่อโคลนที่เก็บซึ่งโฟลเดอร์ที่คุณต้องการส่งออกคือ
  2. ในการสร้างที่เก็บว่างบนผู้ให้บริการโฮสติ้งของคุณเป็น GitHub เพื่อจัดเก็บโฟลเดอร์ที่ส่งออก
  3. เปิดโฟลเดอร์ที่เก็บโคลนและเรียกใช้คำสั่งนี้:

    git subtree push --prefix=YourFolderNameToExport https://github.com/YourUserName/YourNewCleanRepoName master
    

1
git subtreeไม่สามารถใช้ได้ในแพ็คเกจ Cygwin ถ้าคุณต้องการ: stackoverflow.com/a/27116828/2484903
Jack Miller

2

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

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

ฉันไม่รู้เครื่องมือใด ๆ ในการแยกไดเรกทอรีออก ฉันคิดว่าคุณสามารถ git-log บนไดเร็กทอรีเพื่อค้นหาการกระทำทั้งหมดจากนั้นเล่นคอมมิตซ้ำด้วยสิ่งที่ต้องการ git-fast-export?


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