อัพเดต God submodule


242

ฉันไม่ชัดเจนเกี่ยวกับความหมายต่อไปนี้ (จากเอกสารอัปเดต submodule Git ):

... จะทำให้ส่วนหัวของ submodules ยกเว้น--rebaseหรือ--mergeระบุไว้ ...

อย่างไร--rebase/ --mergeสิ่งที่เปลี่ยนแปลง?

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

  • จากภายใน submodules เหล่านี้ฉันสามารถสร้าง branch / modified และใช้ push / pull เหมือนกับที่ใช้ใน repositories ปกติหรือมีสิ่งที่ต้องระวังหรือไม่?
  • ฉันจะก้าวหน้าไปถึงการส่งซับออเดอร์ที่อ้างอิงจากการพูด (ติดแท็ก) 1.0 ถึง 1.1 (แม้ว่าส่วนหัวของที่เก็บต้นฉบับนั้นมีอยู่ที่ 2.0) หรือเลือกการกระทำของสาขาที่ใช้เลย

ในหัวข้อของ "หัวที่ถอดออกได้" ดูได้ที่stackoverflow.com/questions/964876/head-and-orighead-in-gitและstackoverflow.com/questions/237408/…สำหรับตัวอย่างที่ใช้งานได้จริง (ไม่เกี่ยวข้องกับ submodule แต่ยังคงอยู่ )
VonC

"คุณไม่สามารถแก้ไขเนื้อหาของ submodule จากภายในโครงการหลัก": ใช่จริง และฉันได้แก้ไขคำตอบของฉันที่จะหลั่งน้ำตาแสงในบางที่ขัดแย้ง (submodule ที่ไม่สามารถแก้ไขได้ที่คุณยังสามารถปรับเปลี่ยนจาก repo โครงการหลัก!)
VonC

คำตอบ:


304

นี้หน้า GitProไม่สรุปผลของการปรับปรุงการคอมไพล์ submodule อย่าง

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

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


หมายเหตุมีนาคม 2013:

ดังที่กล่าวไว้ใน " การติดตาม submodule git ล่าสุด " ตอนนี้ submodule (git1.8.2) สามารถติดตามสาขาได้

# add submodule to track master branch
git submodule add -b master [URL to Git repo];

# update your submodule
git submodule update --remote 
# or (with rebase)
git submodule update --rebase --remote

ดู " git submodule update --remotevsgit pull "

คำตอบของMindToothแสดงให้เห็นถึงการอัพเดทด้วยตนเอง (โดยไม่มีการกำหนดค่าในเครื่อง):

git submodule -q foreach git pull -q origin master

ในทั้งสองกรณีที่จะเปลี่ยนการอ้างอิง submodules ( gitlink , รายการพิเศษในดัชนี repo หลัก ) และคุณจะต้องเพิ่มกระทำและผลักดันการอ้างอิงดังกล่าวจาก repo หลัก
ครั้งต่อไปที่คุณจะโคลนผู้ปกครอง repo มันจะเติมข้อมูลเพื่อสะท้อนการอ้างอิง SHA1 ใหม่เหล่านั้น

ส่วนที่เหลือของคำตอบนี้ให้รายละเอียดเกี่ยวกับคุณลักษณะ submodule แบบคลาสสิก (อ้างอิงถึงการกระทำที่คงที่ซึ่งเป็นจุดที่อยู่เบื้องหลังแนวคิดของ submodule)


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

การสลับสาขากับ submodules ในพวกเขายังสามารถหากิน หากคุณสร้างสาขาใหม่เพิ่ม submodule ที่นั่นแล้วเปลี่ยนกลับเป็นสาขาที่ไม่มี submodule นั้นคุณยังคงมีไดเรกทอรี submodule เป็นไดเรกทอรีที่ไม่ได้ติดตาม:


ดังนั้นเพื่อตอบคำถามของคุณ:

ฉันสามารถสร้างสาขา / การดัดแปลงและใช้การผลัก / ดึงเหมือนที่ฉันทำใน repos ปกติหรือมีสิ่งที่ต้องระวังหรือไม่

คุณสามารถสร้างสาขาและการปรับเปลี่ยนแบบพุช

คำเตือน (จากGit Submodule Tutorial ): เผยแพร่ (ดัน) การเปลี่ยนแปลง submodule ทุกครั้งก่อนที่จะเผยแพร่ (กด) การเปลี่ยนแปลงของ superproject ที่อ้างอิงถึงมัน หากคุณลืมที่จะเผยแพร่การเปลี่ยนแปลง submodule คนอื่นจะไม่สามารถโคลนที่เก็บ

ฉันจะเลื่อนระดับอนุเสาวรีย์ที่อ้างอิงจากการพูด (ติดแท็ก) 1.0 เป็น 1.1 ได้อย่างไร (แม้ว่าหัวหน้า repo ดั้งเดิมจะมีอยู่ที่ 2.0)

หน้า "การทำความเข้าใจกับโมดูลย่อย " สามารถช่วยได้

God submodules ถูกนำมาใช้โดยใช้สองส่วนที่เคลื่อนไหว:

  • .gitmodulesไฟล์และ
  • วัตถุต้นไม้ชนิดพิเศษ

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


จากหน้า submodule git

คุณไม่สามารถแก้ไขเนื้อหาของ submodule จากภายในโครงการหลัก

ถูกต้อง 100%: คุณไม่สามารถแก้ไข submodule เพียงอ้างถึงข้อผูกพันข้อใดข้อหนึ่ง

นี่คือเหตุผลที่เมื่อคุณแก้ไข submodule จากภายในโครงการหลักคุณ:

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

submodule ช่วยให้คุณมี การพัฒนาวิธีการตามองค์ประกอบที่โครงการหลักหมายถึงการกระทำที่เฉพาะเจาะจงของส่วนประกอบอื่น ๆ (ที่นี่ "ที่เก็บ Git อื่น ๆ ประกาศเป็นโมดูลย่อย")

submodule เป็นเครื่องหมาย (กระทำ) ไปยังพื้นที่เก็บข้อมูล Git อื่นซึ่งไม่ได้ถูกผูกไว้โดยวงจรการพัฒนาโครงการหลัก: มัน ("อื่น ๆ " Git repo) สามารถวิวัฒนาการได้อย่างอิสระ
มันขึ้นอยู่กับโครงการหลักที่จะเลือกจาก repo อื่น ๆ ไม่ว่าจะเป็นการกระทำที่ต้องการ

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

แต่แนวคิดหลักยังคงอยู่: อ้างอิงองค์ประกอบเฉพาะซึ่ง:

  • มีวงจรชีวิตของตัวเอง
  • มีชุดแท็กของตนเอง
  • มีการพัฒนาของตัวเอง

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

หากองค์ประกอบสามารถพัฒนาได้ในเวลาเดียวกับโครงการหลักของคุณ (เพราะการดัดแปลงใด ๆ ในโครงการหลักจะเกี่ยวข้องกับการแก้ไขไดเรกทอรีย่อยและในทางกลับกัน) ก็จะเป็น "submodule" ไม่มากไปกว่า subtree merge (นำเสนอในคำถามการถ่ายโอนฐานรหัสดั้งเดิมจาก cvs ไปยังที่เก็บแบบกระจาย ) เชื่อมโยงประวัติของ repo Git ทั้งสองเข้าด้วยกัน

นั่นช่วยทำความเข้าใจธรรมชาติที่แท้จริงของ Submodules Git หรือไม่?


77
ว้าว. นั่นเป็นคำอธิบายที่ยาวสำหรับบางสิ่งที่เป็นหลักที่ง่ายพอที่จะทำให้ผู้มาใหม่ตกใจกลัวเพียงแค่ยึดกับ svn: externals ;-)
conny

2
@conny แต่ที่ผมรายละเอียดใน " ทำไมมี submodules คอมไพล์ไม่เข้ากันกับภายนอก SVN " submodules มีพื้นฐานsvn:externalsที่แตกต่างและเข้ากันไม่ได้กับ
VonC

1
ขออภัยที่จะตอบคำถามของฉันเองฉันรวบรวม cd'ing ใน submodule และ git ชำระเงินเป็น sha หรือ git pull / fetch จะทำได้ดี จากนั้นคอมมิตการอัพเดตในที่เก็บโลคัล
Henrik

2
@hced: คุณยังสามารถเข้าถึง submodules ทั้งหมดได้ในครั้งเดียวโดยใช้git submodule foreach
Dav Clark

1
.. ยังไม่ได้รับมัน มีคำอธิบายที่ง่ายขึ้นในเว็บอยู่ที่ไหนบ้าง?
eugene

135

ในการอัพเดทแต่ละ submodule คุณสามารถเรียกใช้คำสั่งต่อไปนี้ (ที่รูทของที่เก็บ):

git submodule -q foreach git pull -q origin master

คุณสามารถลบตัวเลือก-qเพื่อทำตามกระบวนการทั้งหมด


15
หากคุณเพิ่งเรียกใช้git submodule update --init --recursiveจากรูทมันจะทำให้พวกมันทั้งหมดวนซ้ำและเริ่มต้นถ้ายังไม่ได้
Sam Soffes

10
@SamSoffes ที่ให้บริการวัตถุประสงค์ที่แตกต่างอย่างสิ้นเชิง การอัปเดต submodules จะตรวจสอบ submodules ที่คอมมิทที่พวกเขากำลังชี้ไป (ไม่จำเป็นต้องเป็นคอมมิทล่าสุด) โซลูชันในคำตอบข้างต้นจะอัพเดตการกระทำของแต่ละ submodule ให้เป็น HEAD ล่าสุดจากแหล่งกำเนิด / มาสเตอร์
indragie

7
วิธีการใหม่ของฉัน:git submodule update --rebase --remote
MindTooth

19

เพื่อที่อยู่--rebaseกับ--mergeตัวเลือก :

สมมติว่าคุณมีพื้นที่เก็บข้อมูล super A และ submodule B และต้องการทำงานใน submodule B คุณทำการบ้านและรู้ว่าหลังจากโทร

git submodule update

คุณอยู่ในสถานะ HEAD-less ดังนั้นการกระทำใด ๆ ที่คุณทำ ณ จุดนี้ยากที่จะกลับไป ดังนั้นคุณได้เริ่มทำงานในสาขาใหม่ใน submodule B

cd B
git checkout -b bestIdeaForBEver
<do work>

ในขณะที่คนอื่นในโครงการ A ตัดสินใจว่ารุ่น B ที่ยอดเยี่ยมที่สุดคือสิ่งที่ A สมควรได้รับ คุณเลิกนิสัยรวมการเปลี่ยนแปลงล่าสุดและปรับปรุง submodules ของคุณ

<in A>
git merge develop
git submodule update

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

git merge develop
git submodule update --rebase

Fast-forwarded bestIdeaForBEver to b798edfdsf1191f8b140ea325685c4da19a9d437.
Submodule path 'B': rebased into 'b798ecsdf71191f8b140ea325685c4da19a9d437'

ตอนนี้ความคิดที่ดีที่สุดสำหรับ B ได้ถูกลดระดับลงบนความมุ่งมั่นใหม่และที่สำคัญกว่านั้นคุณยังคงอยู่ในสาขาการพัฒนาของคุณสำหรับ B ไม่ใช่ในสภาวะหัวขาด!

( --mergeจะรวมการเปลี่ยนแปลงจาก beforeUpdateSHA เป็น afterUpdateSHA ในสาขาที่ทำงานของคุณซึ่งต่างจากการรีบูตการเปลี่ยนแปลงของคุณไปยัง afterUpdateSHA)


7

Git 1.8.2 มีตัวเลือกใหม่--remoteซึ่งจะเปิดใช้งานลักษณะการทำงานนี้อย่างแน่นอน วิ่ง

git submodule update --rebase --remote

จะดึงการเปลี่ยนแปลงล่าสุดจากอัปสตรีมในแต่ละ submodule รีบูตและตรวจสอบการแก้ไขล่าสุดของ submodule เป็นเอกสารที่ทำให้มัน:

--remote

ตัวเลือกนี้ใช้ได้สำหรับคำสั่ง update เท่านั้น แทนที่จะใช้ SHA-1 ที่บันทึกไว้ของ superproject เพื่ออัปเดต submodule ให้ใช้สถานะของสาขาการติดตามระยะไกลของ submodule

สิ่งนี้เทียบเท่ากับการทำงานgit pullในแต่ละ submodule ซึ่งโดยทั่วไปคือสิ่งที่คุณต้องการ

(นี่ถูกคัดลอกมาจากคำตอบนี้)


หากคุณตัดสินใจที่จะตอบคำถามที่เก่ากว่าซึ่งมีคำตอบที่ถูกต้องและถูกต้องแล้วการเพิ่มคำตอบใหม่ในช่วงปลายวันอาจไม่ได้รับเครดิตใด ๆ หากคุณมีข้อมูลใหม่ที่โดดเด่นหรือคุณมั่นใจว่าคำตอบอื่น ๆ นั้นผิดทั้งหมดโดยเพิ่มคำตอบใหม่ แต่ 'ยังมีคำตอบอื่น' ให้ข้อมูลพื้นฐานเดียวกันนานหลังจากคำถามถูกถามมักจะ ' คุณไม่ได้รับเครดิตมาก ไม่มีคำอธิบายว่าสิ่งนี้ทำอะไร - แม้แต่ลิงค์ไปยังเอกสารภายนอก (ซึ่งไม่เพียงพอ)
Jonathan Leffler

2
มันไม่ใช่ "ยังมีคำตอบอื่น" เนื่องจากไม่มีคำตอบอื่นที่มีคำสั่งนี้ (พิสูจน์ว่าฉันผิด) คำตอบอื่น ๆ ใช้งานไม่ได้สำหรับฉันความคิดเห็นนี้ไม่ได้ดังนั้นฉันจึงตัดสินใจที่จะโพสต์มันเป็นคำตอบในขณะที่ให้เครดิตกับเจ้าของเดิม ดังนั้นให้พิจารณาลบ downvote ของคุณ
Iulian Onofrei

มีความคิดเห็นโดยMindToothจากปี 2015 โดยบอกว่านี่คือสิ่งที่พวกเขาทำ คุณไม่ได้ให้คำอธิบายเกี่ยวกับสิ่งนี้ (แม้ว่าคุณจะพูดถึง MindTooth แต่ไม่มีคำอธิบายที่แท้จริงเกี่ยวกับสิ่งที่คุณหมายถึงโดย - ฝัง URL เช่นเดียวกับในความคิดเห็นนี้จะช่วยได้) คุณไม่พูดว่าทำไมจึงเป็นความคิดที่ดี คุณไม่ได้ให้คำเตือนใด ๆ ในมุมมองของฉันนี่ไม่ใช่คำตอบที่เป็นประโยชน์เพราะมันทำให้เกิดคำถามมากกว่าที่จะแก้ไข
Jonathan Leffler

1
จากนั้นฉันหมายความว่ามันใช้งานได้แทนที่จะไม่ทำงาน ผมเชื่อว่าถ้าคนอื่น ๆ ก็จะเห็นคำตอบนี้พวกเขาจะดีใจเพราะมันทำงาน สำหรับสิ่งเช่นนี้ผู้คนส่วนใหญ่ต้องการทราบคำสั่งที่อัปเดต submodule git ไม่ใช่วิธีการนำไปใช้
Iulian Onofrei

ฉันแก้ไขคำตอบเพื่อพิสูจน์ว่าคุณผิดด้วยเช่นกันstackoverflow.com/questions/1979167/git-submodule-update/ ...... !!!
Iulian Onofrei
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.