ฉันจะเปลี่ยนการเปลี่ยนแปลงเป็น submodule git ได้อย่างไร


270

ฉันมี submodule git (RestKit) ซึ่งฉันได้เพิ่มลงใน repo ของฉัน

ฉันบังเอิญเปลี่ยนไฟล์บางไฟล์ในนั้นและฉันต้องการกลับไปเป็นเวอร์ชั่นต้นฉบับ เพื่อที่จะทำเช่นนั้นฉันพยายามที่จะวิ่ง

Mac:app-ios user$ git submodule update RestKit

แต่อย่างที่คุณเห็นที่นี่สิ่งนี้ไม่ได้ผลเพราะมันยังเป็น "เนื้อหาที่ถูกแก้ไข":

Mac:app-ios user$ git status
...
#   modified:   RestKit (modified content)

แม้

Mac:app-ios user$ git submodule update -f RestKit 

จะไม่คืนค่าไฟล์ที่แก้ไขในเครื่อง
ฉันจะรีเซ็ตเนื้อหาของ submodule นั้นได้อย่างไร


ถ้าไม่ได้ทำงานครั้งแรกลองระบุสาขาที่ห่างไกลกับgit reset --hard git reset --hard origin/<branch_name>
Jerry K.

คำตอบ:


208

ย้ายไปยังไดเร็กทอรีของ submodule จากนั้นทำ a git reset --hardเพื่อรีเซ็ตไฟล์ที่แก้ไขทั้งหมดเป็นสถานะที่คอมมิทครั้งล่าสุด โปรดทราบว่าการดำเนินการนี้จะเป็นการยกเลิกการเปลี่ยนแปลงที่ไม่ได้กระทำทั้งหมด


6
การปรับปรุง submodule git (แม้ไม่มี - เริ่มต้น) ทำงานให้ฉันที่จะละทิ้ง "การเปลี่ยนแปลง" submodule เมื่อฉันไม่ได้เปลี่ยนแปลงอะไรจริง ๆ หากคุณไปที่ไดเรกทอรี submodule และสถานะ git ว่างเปล่าลองทำสิ่งนี้แทนการรีเซ็ต
ดีเอ็นเอผสมผสาน

16
git submodule update --initทำงานให้ฉัน ถ้าไม่มี--initมันก็ไม่ทำงานเลย
ต่อ Lundberg

สุดยอด !! ฉันทำการเปลี่ยนแปลง submodule ใน repo ของฉันที่ฉันนำเข้า และจะคืนกลับเป็นสิ่งที่ควรจะเป็น
Noitidart

2
รีเซ็ต - ฮาร์ดไม่ทำงานสำหรับฉัน submodule ของฉันยังคงไม่สามารถ deinit ได้เนื่องจากการเปลี่ยนแปลงในเครื่อง
2559

33
นอกเหนือจาก @markshiz git submodule update -f --initสำหรับกรณีของฉัน
otiai10

280

หากคุณต้องการทำเช่นนี้กับทุก submodules โดยไม่ต้องเปลี่ยนไดเรกทอรีคุณสามารถทำได้

git submodule foreach git reset --hard

คุณยังสามารถใช้การตั้งค่าสถานะเวียนซ้ำเพื่อใช้กับ submodules ทั้งหมด:

git submodule foreach --recursive git reset --hard


7
วิธีนี้ใช้งานได้ดีกว่าสำหรับการทำงานอัตโนมัติมากกว่าการลองซีดีลงในแต่ละไดเรกทอรี
Travis Castillo

4
โปรดทราบว่าคุณอาจต้องการgit submodule foreach --recursive git clean -x -f -d
yoyo

1
บนเครื่องของฉัน (Windows ที่ใช้ Git 2.22.0) ฉันต้องการเครื่องหมายคำพูดเดี่ยวรอบคำสั่ง git ที่สองเมื่อใช้แฟล็ก --recursive หรือไม่ทำงาน: git submodule foreach --recursive 'git clean -x -f -d'
aatwo

196

วิธีที่ไม่ปลอดภัยมากกว่าคำตอบก่อนหน้านี้ทั้งหมด:

git submodule deinit -f .
git submodule update --init

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


1
น่าเสียดายที่นี่ไม่ได้ผลในกรณีของฉัน (ด้วยไฟล์ในเครื่องที่แก้ไขในซับทอล git) คำสั่ง "update --init" spewserror: Your local changes to the following files would be overwritten by checkout
rogerdpack

หากต้องการอัปเดต submodule โดยเฉพาะให้ทำ: $ git submodule deinit -f - <submodule_path> จากนั้น $ git submodule update --init - <submodule_path>
Priyank

ฉันลองใช้วิธีการทั้งหมดข้างต้นจนกว่าจะถึงวิธีนี้ สำหรับฉันนี้เป็นเพียงคนเดียวที่ได้รับการคอมไพล์ของฉันกำลังมอง "สะอาด" (โดยไม่ต้อง*ในของฉันPS1ที่git status -unoไม่สามารถที่จะอธิบาย)
Guy Rapaport

60

ดีสำหรับฉันมี

git reset --hard

เพียงแค่รีเซ็ต submodule เป็นสถานะที่มันเช็คเอาต์ไม่จำเป็นต้อง repo หลักอ้างอิงกระทำ / รัฐ ฉันจะยังมี "เนื้อหาที่แก้ไข" อย่างที่ OP บอก ดังนั้นเพื่อที่จะให้ submodule กลับไปที่การคอมมิทที่ถูกต้องฉันรัน:

git submodule update --init

จากนั้นเมื่อฉันทำgit statusมันสะอาดบน submodule


น่าเสียดายที่submodule update --initดูเหมือนจะไม่คืนค่าการปรับเปลี่ยนท้องถิ่นในกรณีของฉันต่อไป: |
rogerdpack

48

ทำลำดับ 4 ขั้นตอน:

git submodule foreach git reset --hard HEAD
git submodule update
git submodule foreach "git checkout master; git pull"
git submodule foreach git clean -f

2
คนเดียวที่ช่วยฉันเช่นกัน
Victor Sergienko

คำถามหาก submodule เป็นไฟล์ใหม่จะไม่มีไฟล์. git อยู่ในไดเรกทอรีนั้นใช่ไหม ฟองคำสั่ง git จะไปที่ repo parent หรือไม่
santiago arizti

1
@ jiahut แม้หลังจากทำเช่นนี้แล้วฉันยังมี "(คอมมิทใหม่") ถัดจาก submodule เมื่อทำ 'สถานะ git' จากผู้ปกครอง?
David Doria

1
@DavidDoria git submodule updateเป็นสิ่งที่แก้ไข(new commits)สำหรับฉัน
ubershmekel

31

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

git submodule update -f --recursive

11

ลองแรกนี้ตามที่คนอื่นพูด:

git submodule update --init

หากวิธีนี้ใช้ไม่ได้ผลให้เปลี่ยนเป็นไดเร็กทอรี submodule และใช้คำสั่งต่อไปนี้เพื่อดูว่ามีการเปลี่ยนแปลงกับ submodule หรือไม่:

git status

หากมีการเปลี่ยนแปลงใน submodule ของคุณให้กำจัดมัน ยืนยันว่าคุณไม่เห็นการเปลี่ยนแปลงใด ๆ เมื่อคุณเรียกใช้ "สถานะ git"

ถัดไปกลับไปที่พื้นที่เก็บข้อมูลหลักและเรียกใช้ "git submodule update --init" อีกครั้ง


9

ตั้งแต่ Git 2.14 (ไตรมาสที่ 3 ปี 2560) คุณไม่จำเป็นต้องเข้าไปในแต่ละ submodule เพื่อทำgit reset(ตามgit submodule foreach git reset --hard)

นั่นเป็นเพราะการรีเซ็ต git เองรู้แล้วว่าจะต้องไปยัง submodules ซ้ำ ๆ

ดูกระทำ 35b96d1 (21 เมษายน 2017) และกระทำ f2d4899 , กระทำ 823bab0 , กระทำ cd279e2 (18 เมษายน 2017) โดยสเตฟานสนั่น (stefanbeller )
(รวมโดยJunio C Hamano - gitster-ในการกระทำ 5f074ca , 29 พฤษภาคม 2017)

builtin / reset: เพิ่ม --recrec-submodules switch

git-reset เป็นอีกหนึ่งเครื่องมือจัดการต้นไม้ที่ใช้งานได้ซึ่งควรสอนเกี่ยวกับ submodules

เมื่อผู้ใช้ใช้ git-reset และขอให้เรียกคืนไปยัง submodules สิ่งนี้จะรีเซ็ต submodules เป็นชื่อวัตถุตามที่บันทึกใน superproject โดยถอด HEADs ออก

คำเตือน : ความแตกต่างระหว่าง:

  • git reset --hard --recurse-submodule และ
  • git submodule foreach git reset --hard

คืออดีตจะรีเซ็ตแผนผังการทำงาน repo หลักของคุณเนื่องจากหลังจะรีเซ็ตต้นไม้การทำงานย่อยเท่านั้น
ดังนั้นควรใช้ด้วยความระมัดระวัง


7

สำหรับ git <= 2.13 ทั้งสองคำสั่งที่รวมกันควรรีเซ็ต repos ของคุณด้วย submodules แบบเรียกซ้ำ:

git submodule foreach --recursive git reset --hard
git submodule update --recursive --init

3

สิ่งนี้ใช้ได้กับห้องสมุดของเราที่ใช้ GIT v1.7.1 ซึ่งเรามี repo แพ็คเกจ DEV และ repo แพ็คเกจสด ที่เก็บของตัวเองไม่มีอะไรนอกจากเปลือกเพื่อทำแพคเกจสินทรัพย์สำหรับโครงการ submodules ทั้งหมด

การถ่ายทอดสดนั้นไม่เคยมีการอัพเดทอย่างจงใจอย่างไรก็ตามอาจมีไฟล์แคชหรืออุบัติเหตุเกิดขึ้นทำให้ repo สกปรก ใหม่ submodules เพิ่ม DEV จะต้องเริ่มต้นภายในสดเช่นกัน

แพ็คเกจที่เก็บใน DEV

ที่นี่เราต้องการดึงการเปลี่ยนแปลงอัปสตรีมทั้งหมดที่เรายังไม่ทราบจากนั้นเราจะอัปเดตที่เก็บแพ็กเกจของเรา

# Recursively reset to the last HEAD
git submodule foreach --recursive git reset --hard

# Recursively cleanup all files and directories
git submodule foreach --recursive git clean -fd

# Recursively pull the upstream master
git submodule foreach --recursive git pull origin master

# Add / Commit / Push all updates to the package repo
git add .
git commit -m "Updates submodules"
git push   

ที่เก็บแพคเกจในการถ่ายทอดสด

ที่นี่เราต้องการดึงการเปลี่ยนแปลงที่กำหนดให้กับที่เก็บ DEV แต่ไม่ทราบการเปลี่ยนแปลงต้นน้ำ

# Pull changes
git pull

# Pull status (this is required for the submodule update to work)
git status

# Initialize / Update 
git submodule update --init --recursive

2

หากคุณต้องการยกเลิกการเปลี่ยนแปลงทั้งหมดในที่เก็บทั้งหมดพร้อมกับโมดูลย่อยคุณสามารถใช้

git restore . --recurse-submodules

การดำเนินการนี้จะยกเลิกการเปลี่ยนแปลงทั้งหมดที่เกิดขึ้นในที่เก็บและในโมดูลย่อย


0

วิธีของฉันในการรีเซ็ต submodules ทั้งหมด (โดยไม่ต้องถอดและรักษาสาขา "master" ของพวกเขา):

git submodule foreach 'การชำระเงินหลัก git && รีเซ็ต git - ฮาร์ด $ sha1'

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