อัปเดต Git submodule เป็นคอมมิทล่าสุดที่กระทำ


853

ฉันมีโครงการที่มี submodule Git มันมาจาก URL ของ ssh: // ... และเมื่อส่งมอบแล้ว A. Commit B ถูกส่งไปยัง URL นั้นแล้วและฉันต้องการให้ submodule ทำการดึงข้อมูลคอมมิชชันและเปลี่ยนมัน

ตอนนี้ความเข้าใจของฉันคือสิ่งที่git submodule updateควรทำ แต่ก็ไม่เป็นเช่นนั้น มันไม่ได้ทำอะไรเลย (ไม่มีเอาท์พุทรหัสออกจากความสำเร็จ) นี่คือตัวอย่าง:

$ mkdir foo
$ cd foo
$ git init .
Initialized empty Git repository in /.../foo/.git/
$ git submodule add ssh://user@host/git/mod mod
Cloning into mod...
user@host's password: hunter2
remote: Counting objects: 131, done.
remote: Compressing objects: 100% (115/115), done.
remote: Total 131 (delta 54), reused 0 (delta 0)
Receiving objects: 100% (131/131), 16.16 KiB, done.
Resolving deltas: 100% (54/54), done.
$ git commit -m "Hello world."
[master (root-commit) 565b235] Hello world.
 2 files changed, 4 insertions(+), 0 deletions(-)
 create mode 100644 .gitmodules
 create mode 160000 mod
# At this point, ssh://user@host/git/mod changes; submodule needs to change too.
$ git submodule init
Submodule 'mod' (ssh://user@host/git/mod) registered for path 'mod'
$ git submodule update
$ git submodule sync
Synchronizing submodule url for 'mod'
$ git submodule update
$ man git-submodule 
$ git submodule update --rebase
$ git submodule update
$ echo $?
0
$ git status
# On branch master
nothing to commit (working directory clean)
$ git submodule update mod
$ ...

ฉันได้ลองgit fetch modแล้วซึ่งดูเหมือนจะดึงข้อมูลได้ (แต่ไม่สามารถทำได้เพราะมันไม่ได้รับรหัสผ่าน!) แต่git logและgit showปฏิเสธการมีอยู่ของคอมมิทใหม่ ป่านนี้ฉันเพิ่งได้รับrmโมดูลและเพิ่มอีกครั้ง แต่นี่เป็นทั้งหลักการและน่าเบื่อในทางปฏิบัติ


5
คำตอบของ David Z ดูเหมือนจะเป็นวิธีที่ดีกว่าในการทำเช่นนี้ - ตอนนี้ Git มีฟังก์ชั่นที่คุณต้องการใน--remoteตัวเลือกบางทีมันอาจจะมีประโยชน์ที่จะทำเครื่องหมายว่าเป็นคำตอบที่ยอมรับมากกว่าวิธีการ "ด้วยมือ" ในคำตอบของ Jason
Mark Amery

1
ฉันเห็นด้วยอย่างมากกับ @MarkAmery ในขณะที่ Jason ให้วิธีแก้ปัญหาการทำงานมันไม่ใช่วิธีที่ตั้งใจทำเพราะปล่อยให้ตัวชี้การส่งข้อมูลของ submodule ไปที่ตัวระบุการกระทำผิด ใหม่--remoteนี้เป็นทางออกที่ดีกว่าในเวลานี้และเนื่องจากคำถามนี้เชื่อมโยงกับ Github Gist เกี่ยวกับ submodules ฉันรู้สึกว่ามันจะดีกว่าสำหรับผู้อ่านที่เข้ามาเพื่อดูคำตอบใหม่
MutantOctopus

สัมผัสที่ดีด้วยhunter2รหัสผ่าน: o)
lfarroco

คำตอบ:


1458

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

ดังนั้นโดยสรุป:

# Get the submodule initially
git submodule add ssh://bla submodule_dir
git submodule init

# Time passes, submodule upstream is updated
# and you now want to update

# Change to the submodule directory
cd submodule_dir

# Checkout desired branch
git checkout master

# Update
git pull

# Get back to your project root
cd ..

# Now the submodules are in the state you want, so
git commit -am "Pulled down update to submodule_dir"

หรือถ้าคุณเป็นคนไม่ว่าง:

git submodule foreach git pull origin master

335
git submodule foreach git pull
Mathias Bynens

87
@Nicklas git submodule foreach git pull origin masterในกรณีที่ใช้
Mathias Bynens

54
ณ จุดนี้ด้วยการแก้ไขทั้งหมดเหล่านี้ไปยังการแก้ไขฉันต้องการใครสักคนที่จะเขียนโพสต์บล็อกอธิบายและชี้ให้ฉันมี โปรด.
Suz

25
ปรับปรุงวิธีการ 'foreach' เล็กน้อย - คุณอาจต้องการเพิ่ม - เรียกใช้ซ้ำในกรณีที่คุณมี submodules ภายใน submodules ดังนั้น: git submodule foreach --recursive git pull origin master.
orion elenzil

4
@Abdull -aสวิตช์สำหรับgit commit"บอกให้ [บอก] คำสั่งให้สเตจไฟล์ที่ถูกแก้ไขและลบโดยอัตโนมัติ แต่ไฟล์ใหม่ที่คุณไม่ได้บอก Git จะไม่ได้รับผลกระทบ"
godfrzero

473

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

git submodule update --remote --merge

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

--remote

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

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


4
"เทียบเท่ากับการทำงานgit pullในแต่ละ submodule"เพื่อชี้แจงไม่มีความแตกต่าง (จากมุมมองของผู้ใช้) ระหว่างคำตอบของคุณและgit submodule foreach git pull?
Dennis

3
@ เดนนิสมันทำสิ่งเดียวกัน แต่ฉันไม่แน่ใจว่าฟังก์ชั่นเหมือนกันหรือไม่ อาจมีความแตกต่างเล็กน้อยที่ฉันไม่รู้เช่นในวิธีที่คำสั่งทั้งสองตอบสนองต่อการตั้งค่าบางอย่าง
David Z

5
ฉันหวังว่าฉันจะสามารถโหวต 10,000 เท่านี้ได้ ทำไมสิ่งนี้ถึงไม่ปรากฏในเอกสารของ git? การกำกับดูแลอย่างมาก
serraosays

4
สำหรับฉันแล้วพวกเขาต่างกันอย่างมีนัยสำคัญมาก foreach git pullตรวจสอบพวกเขาเท่านั้น แต่ไม่ได้ปรับปรุงตัวชี้ของ repo หลักเพื่อชี้ไปที่กระทำใหม่ของ submodule เฉพาะกับ--remoteมันทำให้มันชี้ไปที่กระทำล่าสุด
Ela782

5
ทำไมตัวเลือก --merge มันแตกต่างกันอย่างไร
mFeinstein

127

ในไดเรกทอรีหลักของโครงการให้เรียกใช้:

git submodule update --init

หรือถ้าคุณมีการเรียกใช้ submodules แบบเรียกซ้ำ:

git submodule update --init --recursive

บางครั้งสิ่งนี้ยังใช้งานไม่ได้เพราะอย่างใดคุณมีการเปลี่ยนแปลงในเครื่องในไดเรกทอรี submodule เฉพาะที่ในขณะที่การปรับปรุง submodule

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

git submodule update --init --recursive

5
นี่คือคำตอบที่แท้จริง ฉันจะผลักดันมันไปยังพื้นที่เก็บข้อมูลระยะไกลของฉันได้หรือไม่
MonsterMMORPG

มันใช้งานได้กับ submodules ใหม่! ฉันสามารถอัปเดตอื่น ๆ ทั้งหมด แต่โฟลเดอร์ของ submodules ใหม่จะยังคงว่างเปล่าจนกว่าฉันจะรันคำสั่งนี้
Alexis Wilke

1
ไม่ดึงการเปลี่ยนแปลงสำหรับ submodules ที่มีอยู่
Sergey G.

73

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

ดังนั้นในกรณีของคุณคุณควรค้นหาการกระทำที่ถูกต้องใน submodule - สมมติว่านั่นคือเคล็ดลับของmaster:

cd mod
git checkout master
git pull origin master

ตอนนี้กลับไปที่โครงการหลักระยะ submodule และยอมรับว่า:

cd ..
git add mod
git commit -m "Updating the submodule 'mod' to the latest version"

ตอนนี้ผลักดันโครงการหลักเวอร์ชันใหม่ของคุณ:

git push origin master

จากจุดนี้เป็นต้นไปหากใครก็ตามที่อัพเดตโครงการหลักของพวกเขาแล้วgit submodule updateพวกเขาจะอัปเดต submodule โดยสมมติว่ามันถูกเริ่มต้น


24

ดูเหมือนว่ามีสองสถานการณ์ที่แตกต่างกันในการสนทนานี้:

สถานการณ์ที่ 1

การใช้พอยน์เตอร์ของที่เก็บพาเรนต์ของฉันไปยัง submodules ฉันต้องการตรวจสอบคอมมิทในแต่ละ submodule ที่ที่เก็บพาเรนต์ชี้ไปที่อาจเป็นไปได้หลังจากทำการวนซ้ำผ่าน submodules ทั้งหมดและอัปเดต / ดึงสิ่งเหล่านี้จากระยะไกล

นี่คือตามที่อธิบายไว้ทำด้วย

git submodule foreach git pull origin BRANCH
git submodule update

สถานการณ์ที่ 2 ซึ่งฉันคิดว่าเป็นสิ่งที่ OP เล็งไปที่

มีสิ่งใหม่เกิดขึ้นใน submodules หนึ่งรายการขึ้นไปและฉันต้องการ 1) ดึงการเปลี่ยนแปลงเหล่านี้และ 2) อัปเดตที่เก็บพาเรนต์เพื่อชี้ไปที่ HEAD (ล่าสุด) คอมมิทเหล่านี้

จะทำโดย

git submodule foreach git pull origin BRANCH
git add module_1_name
git add module_2_name
......
git add module_n_name
git push origin BRANCH

ไม่สามารถใช้งานได้จริงเนื่องจากคุณจะต้องฮาร์ดโค้ด n พา ธ ไปยัง n submodules ทั้งหมดเช่นสคริปต์เพื่ออัปเดตพอยน์เตอร์คอมมิชชันของที่เก็บพาเรนต์

จะเป็นการดีหากมีการวนซ้ำอัตโนมัติผ่านแต่ละ submodule อัปเดตตัวชี้พื้นที่เก็บข้อมูลหลัก (โดยใช้git add) เพื่อชี้ไปที่ส่วนหัวของ submodule

สำหรับสิ่งนี้ฉันทำสคริปต์ Bash ขนาดเล็กนี้:

git-update-submodules.sh

#!/bin/bash

APP_PATH=$1
shift

if [ -z $APP_PATH ]; then
  echo "Missing 1st argument: should be path to folder of a git repo";
  exit 1;
fi

BRANCH=$1
shift

if [ -z $BRANCH ]; then
  echo "Missing 2nd argument (branch name)";
  exit 1;
fi

echo "Working in: $APP_PATH"
cd $APP_PATH

git checkout $BRANCH && git pull --ff origin $BRANCH

git submodule sync
git submodule init
git submodule update
git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"

for i in $(git submodule foreach --quiet 'echo $path')
do
  echo "Adding $i to root repo"
  git add "$i"
done

git commit -m "Updated $BRANCH branch of deployment repo to point to latest head of submodules"
git push origin $BRANCH

หากต้องการเรียกใช้งานให้เรียกใช้งาน

git-update-submodules.sh /path/to/base/repo BRANCH_NAME

รายละเอียดเพิ่มเติม

ก่อนอื่นฉันคิดว่าสาขาที่มีชื่อ $ BRANCH (อาร์กิวเมนต์ที่สอง) มีอยู่ในที่เก็บทั้งหมด รู้สึกอิสระที่จะทำให้สิ่งนี้ซับซ้อนยิ่งขึ้น

คู่แรกของส่วนคือการตรวจสอบว่ามีข้อโต้แย้งบางอย่าง จากนั้นฉันก็ดึงสิ่งล่าสุดของพื้นที่เก็บข้อมูลของผู้ปกครอง (ฉันชอบที่จะใช้ --ff (การส่งต่ออย่างรวดเร็ว) เมื่อใดก็ตามที่ฉันเพิ่งจะดึงฉันมี rebase off, BTW)

git checkout $BRANCH && git pull --ff origin $BRANCH

ดังนั้นการเริ่มต้น submodule บางครั้งอาจมีความจำเป็นถ้ามีการเพิ่ม submodule ใหม่หรือยังไม่ได้เริ่มต้น:

git submodule sync
git submodule init
git submodule update

จากนั้นฉันจะอัปเดต / ดึงข้อมูลทั้งหมด:

git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"

สังเกตสิ่งเล็ก ๆ น้อย ๆ : อย่างแรกเลยฉันกำลังใช้คำสั่ง Git บางคำสั่ง&&- หมายถึงคำสั่งก่อนหน้านี้จะต้องดำเนินการโดยไม่มีข้อผิดพลาด

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

ในที่สุดสุดท้าย|| trueคือการตรวจสอบให้แน่ใจว่าสคริปต์ต่อข้อผิดพลาด ในการทำให้งานนี้ทุกอย่างในการวนซ้ำต้องถูกล้อมด้วยเครื่องหมายคำพูดคู่และคำสั่ง Git จะถูกรวมอยู่ในวงเล็บ (ลำดับความสำคัญของโอเปอเรเตอร์)

ส่วนที่ฉันชอบ:

for i in $(git submodule foreach --quiet 'echo $path')
do
  echo "Adding $i to root repo"
  git add "$i"
done

ทำซ้ำทั้งหมด submodules - ด้วย--quietซึ่งจะเอาเอาท์พุท 'Entering MODULE_PATH' การใช้'echo $path'(ต้องอยู่ในเครื่องหมายคำพูดเดี่ยว) พา ธ ไปยัง submodule จะถูกเขียนไปยังเอาต์พุต

รายการพา ธ ของ submodule แบบสัมพัทธ์นี้จะถูกจับในอาเรย์ ( $(...)) - ในที่สุดวนซ้ำสิ่งนี้และทำgit add $iเพื่ออัพเดตที่เก็บพาเรนต์

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

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

ฉันหวังว่านี่จะเป็นประโยชน์กับใครบางคน


2
! @ # $% ดังนั้นเรากำลังใช้สคริปต์คล้ายกับของคุณ หนึ่งหมายเหตุ: แทนที่จะเป็น `` `git submodule foreach - เงียบ 'echo $ path' '` `เราใช้` `` git submodule foreach - recursive - เงียบ pwd' '' ภายในลูป pwdคำสั่งพิมพ์ที่เหมาะสม 'เส้นทางแน่นอน' สำหรับแต่ละ submodule ปัจจุบัน --recursiveทำให้มั่นใจได้ว่าเราจะไปที่submodules ทั้งหมดรวมถึง submodules-within-submodules -... ที่อาจมีอยู่ในโครงการขนาดใหญ่ ทั้งสองวิธีทำให้เกิดปัญหากับไดเรกทอรีที่มีช่องว่างเช่น/c/Users/Ger/Project\ Files/...นโยบายจึงไม่ควรใช้ช่องว่างในโครงการของเรา
Ger Hobbelt

2
นี่เป็นสิ่งที่ดีและคุณคิดถูกว่ามีคำตอบที่เข้าใจผิดเกี่ยวกับสิ่งที่คำถามนั้นเกิดขึ้น แต่ตามที่คำตอบที่ดีเยี่ยมของ David Z สคริปต์ของคุณไม่จำเป็นเนื่องจากฟังก์ชั่นถูกสร้างขึ้นใน Git ตั้งแต่กลางปี ​​2013 พวกเขาเพิ่ม--remoteตัวเลือก git submodule update --remoteทำงานโดยประมาณตามที่สคริปต์ของคุณทำ
Mark Amery

@ GerHobbelt ขอบคุณ คุณพูดถูกเรามี submodules เพียง 1 ระดับเท่านั้นดังนั้นฉันไม่เคยคิดที่จะทำซ้ำ ฉันจะไม่อัปเดตสคริปต์ก่อนที่ฉันจะมีโอกาสตรวจสอบว่าทำงานได้ตามที่คาดไว้ แต่แน่นอนว่าสคริปต์ของฉันจะใช้งานโมดูลย่อย ในเรื่องของช่องว่างในโฟลเดอร์สิ่งนี้ดูเหมือนจะเป็นเรื่องที่ต้องหลีกเลี่ยง : S
Frederik Struck-Schøning

@ MarkAmery ขอบคุณสำหรับความคิดเห็นของคุณ ฉันเห็นปัญหา 1 ข้อ: ไม่สามารถโต้แย้งได้โดยระบุสาขาสำหรับ submodules จากคู่มือ git: The remote branch used defaults to master, but the branch name may be overridden by setting the submodule.<name>.branch option in either .gitmodules or .git/config (with .git/config taking precedence).ฉันไม่ต้องการแก้ไข. gitmodules หรือ. git / config ทุกครั้งที่ฉันต้องการทำสิ่งนี้กับสาขาอื่นที่ไม่ใช่มาสเตอร์ แต่บางทีฉันอาจจะพลาดบางสิ่งบางอย่าง? นอกจากนี้วิธีการนี้ดูเหมือนว่าจะบังคับให้เกิดการรวมซ้ำแบบซ้ำ
Frederik Struck-Schøning

สิ่งสุดท้าย: ฉันลองใช้วิธีการของ @ DavidZ และดูเหมือนจะไม่ทำสิ่งที่แน่นอนฉันออกไปทำ (และสิ่งที่ op ถามเกี่ยวกับ): การเพิ่ม HEAD กระทำของ submodules ให้กับผู้ปกครอง (เช่น "การปรับปรุงตัวชี้" ) อย่างไรก็ตามมันดูเหมือนว่าจะทำงานได้ดีมาก (และเร็วกว่า) ในการดึงข้อมูลและรวมการเปลี่ยนแปลงล่าสุดในทุก ๆ อนิจจาโดยค่าเริ่มต้นจากสาขาหลักเท่านั้น (เว้นแต่คุณจะแก้ไขไฟล์. gitmodules (ดูด้านบน))
Frederik Struck-Schøning

19

ธรรมดาและเรียบง่ายเพื่อดึงข้อมูล submodules:

git submodule update --init --recursive

และตอนนี้ทำการอัปเดตพวกเขาเป็นสาขาหลักล่าสุด (ตัวอย่าง):

git submodule foreach git pull origin master

12

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

git submodule update --recursive --remote --merge --force

แบบฟอร์มเก่าคือ:

git submodule foreach --quiet git pull --quiet origin

ยกเว้น ... แบบฟอร์มที่สองนี้ไม่ได้ "เงียบ" จริงๆ

ดูกระทำ a282f5a (12 เมษายน 2019) โดยNguyễnTháiNgọc Duy (pclouds )
(ผสานโดยJunio ​​C Hamano - gitster- in f1c9f6c , 25 เม.ย. 2019)

submodule foreach: แก้ไข "<command> --quiet " ไม่ได้รับการเคารพ

โรบินรายงานว่า

git submodule foreach --quiet git pull --quiet origin

ไม่ได้เงียบอีกต่อไป
ควรเงียบก่อนfc1b924 ( submodule: คำsubmoduleสั่งย่อยport ' foreach' จากเชลล์ถึง C, 2018-05-10, Git v2.19.0-rc0) เพราะparseoptไม่สามารถกินตัวเลือกโดยไม่ตั้งใจได้

" git pull" จะทำงานราวกับ--quietว่าไม่ได้รับ

สิ่งนี้เกิดขึ้นเพราะparseoptในsubmodule--helperจะพยายามแยกวิเคราะห์--quietตัวเลือกทั้งสองราวกับว่าเป็นตัวเลือกต่าง ๆ ของหน้าไม่ใช่git-pullของ
ตัวเลือกการแยกวิเคราะห์จะถูกลบออกจากบรรทัดคำสั่ง ดังนั้นเมื่อเราดึงในภายหลังเราจะดำเนินการเพียงแค่นี้

git pull origin

เมื่อโทรผู้ช่วย submodule เพิ่ม " --" ในหน้า " git pull" จะหยุดหาตัวเลือกที่ไม่ได้แยกเป็นของจริงparseopt submodule--helper foreach

PARSE_OPT_KEEP_UNKNOWNจะถูกลบออกตามมาตรการความปลอดภัย parseoptไม่ควรเห็นตัวเลือกที่ไม่รู้จักหรือมีบางอย่างผิดปกติ นอกจากนี้ยังมีการอัพเดตสตริงการใช้งานสองสามอย่างในขณะที่ฉันกำลังดูอยู่

ในขณะนั้นฉันยังเพิ่ม " --" ไปยังคำสั่งย่อยอื่น ๆ ที่ส่งผ่าน " $@" ไปยัง submodule--helperเพื่อ " $@" --something-like-thisในกรณีเหล่านี้เป็นเส้นทางและโอกาสน้อยที่จะ
แต่จุดที่ยังคงอยู่git-submoduleได้แยกวิเคราะห์และจำแนกสิ่งที่เป็นตัวเลือกเส้นทางคืออะไร
submodule--helperไม่ควรพิจารณาเส้นทางที่ผ่านgit-submoduleไปเป็นตัวเลือกแม้ว่าจะมีลักษณะเหมือนกันก็ตาม


และ Git 2.23 (ไตรมาสที่ 3 ปี 2019) แก้ไขปัญหาอื่น: " git submodule foreach" ไม่ได้ป้องกันตัวเลือกบรรทัดคำสั่งที่ส่งไปยังคำสั่งที่จะทำงานในแต่ละ submodule อย่างถูกต้องเมื่อมีการ--recursiveใช้งานตัวเลือก ""

ดูกระทำ 30db18b (24 มิถุนายน 2019) โดยMorian โคลง (momoson )
(ผสานโดยJunio ​​C Hamano - gitster- in 968eecb , 09 Jul 2019)

submodule foreach: แก้ไขการเรียกซ้ำตัวเลือก

โทรศัพท์:

git submodule foreach --recursive <subcommand> --<option>

นำไปสู่ข้อผิดพลาดที่ระบุว่าตัวเลือก --<option>submodule--helperเป็นที่รู้จักกับ
นั่นคือแน่นอนเพียง แต่เมื่อไม่ได้เป็นตัวเลือกที่ถูกต้องสำหรับ<option>git submodule foreach

สาเหตุของการทำเช่นนี้คือการโทรข้างต้นได้รับการแปลภายในเป็นการโทรไปยัง submodule - helper:

git submodule--helper foreach --recursive \
    -- <subcommand> --<option>

การเรียกนี้เริ่มต้นด้วยการเรียกใช้งานคำสั่งย่อยด้วยตัวเลือกภายในการส่งระดับแรกและดำเนินการต่อโดยเรียกการทำซ้ำครั้งถัดไปของการsubmodule foreachโทร

git --super-prefix <submodulepath> submodule--helper \
   foreach --recursive <subcommand> --<option>

ภายใน submodule ระดับแรก โปรดทราบว่าเส้นประสองครั้งที่ด้านหน้าของคำสั่งย่อยหายไป

ปัญหานี้เริ่มเกิดขึ้นเมื่อเร็ว ๆ นี้เนื่องจากการPARSE_OPT_KEEP_UNKNOWNตั้งค่าสถานะสำหรับการแยกวิเคราะห์อาร์กิวเมนต์git submodule foreachถูกลบออกเมื่อคอมมิชชัน a282f5a
ดังนั้นตัวเลือกที่ไม่รู้จักจะถูกร้องเรียนในขณะนี้เนื่องจากการแยกอาร์กิวเมนต์ไม่สิ้นสุดอย่างถูกต้องโดยเส้นประสองครั้ง

การกระทำนี้แก้ไขปัญหาได้โดยการเพิ่ม double dash ด้านหน้าคำสั่งย่อยในระหว่างการเรียกซ้ำ


7
git pull --recurse-submodules

สิ่งนี้จะดึงข้อผูกพันล่าสุดทั้งหมด


4

ในกรณีของฉันฉันต้องการ gitอัปเดตเป็นไฟล์ล่าสุดและในเวลาเดียวกันก็เติมไฟล์ที่หายไปอีกครั้ง

ต่อไปนี้คืนค่าไฟล์ที่หายไป (ขอบคุณ--forceซึ่งดูเหมือนจะไม่ได้รับการกล่าวถึงที่นี่) แต่มันไม่ได้ดึงความมุ่งมั่นใหม่ ๆ :

git submodule update --init --recursive --force

สิ่งนี้ทำ:

git submodule update --recursive --remote --merge --force


3

@ Jason ถูกต้อง แต่ก็ไม่ใช่ทั้งหมด

ปรับปรุง

อัปเดต submodules ที่ลงทะเบียนเช่นโคลน submodules ที่หายไปและตรวจสอบการคอมมิทที่ระบุไว้ในดัชนีของที่เก็บที่มี สิ่งนี้จะทำให้หัวหน้า submodules ถูกถอดออกเว้นแต่ว่า --rebase หรือ --merge ถูกระบุหรือ submodule ที่สำคัญ $ name.update ถูกตั้งค่าเป็น rebase หรือ merge

ดังนั้นgit submodule updateไม่ชำระเงิน แต่มันคือการกระทำในดัชนีของพื้นที่เก็บข้อมูลที่มี ยังไม่ทราบถึงความมุ่งมั่นใหม่ทั้งหมด เพื่อไป submodule ของคุณได้รับการกระทำที่คุณต้องการและกระทำรัฐ submodule git submodule updateปรับปรุงในพื้นที่เก็บข้อมูลหลักแล้วทำ


1
ดูเหมือนว่าถ้าฉันย้าย submodule ไปยังการคอมมิชชันที่ต่างกันจากนั้นรันการgit submodule updateอัพเดตจะย้าย submodule ไปยังการคอมมิทที่ระบุไว้ใน HEAD ปัจจุบันของ superproject (สิ่งที่กระทำล่าสุดใน superproject บอกว่าโครงการย่อยควรจะอยู่ที่ - พฤติกรรมนี้หลังจากคำอธิบายในโพสต์ของ Jason ดูเหมือนว่ามีเหตุผลสำหรับฉัน) มันก็ดูเหมือนจะดึง แต่ในกรณีที่โครงการย่อยอยู่ในการกระทำที่ผิด ซึ่งเพิ่มความสับสนให้ฉัน
Thanatos

2

นี่คือหนึ่งสายการบินที่ยอดเยี่ยมในการอัปเดตทุกอย่างให้เป็นรุ่นล่าสุดในต้นแบบ:

git submodule foreach 'git fetch origin --tags; git checkout master; git pull' && git pull && git submodule update --init --recursive

ขอบคุณ Mark Jaquith


2

หากคุณไม่รู้จักสาขาโฮสต์ให้ทำสิ่งนี้:

git submodule foreach git pull origin $(git rev-parse --abbrev-ref HEAD)

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


0

หากคุณกำลังมองหาmasterสาขาการชำระเงินสำหรับแต่ละ submodule - คุณสามารถใช้คำสั่งต่อไปนี้เพื่อจุดประสงค์นั้น:

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