ความหมายของการเช็คเอาต์ Git ขีดคั่นสองครั้ง


274

ความหมายของเครื่องหมายขีดกลางคู่หน้าชื่อไฟล์ในคำสั่ง git นี้คืออะไร

git checkout --ours -- path/to/file.txt
git checkout --theirs -- path/to/file.txt

พวกมันบังคับเหรอ? มันเทียบเท่ากับ

git checkout --ours path/to/file.txt
git checkout --theirs path/to/file.txt

24
มันคือการแสดงออกของเปลือก ดูunix.stackexchange.com/questions/11376/…
iltempo

15
@iltempo: มันแตกต่างกันเล็กน้อยสำหรับ Git สำหรับ Git มันแยกต้นไม้ออกจากเส้นทางในกรณีที่ต้นไม้และเส้นทางอาจมีลักษณะเหมือนกัน
Dietrich Epp

@Dietrich_Epp ฉันเห็น. ขอบคุณสำหรับการชี้แจง
iltempo

จัดทำเป็นเอกสารไว้ในstackoverflow.com/a/1192194/6309
VonC

3
มันเป็นสิ่งที่ซ้ำกัน แต่สิ่งที่ซ้ำกันนี้เป็นอย่างน้อย googleable โดยคำค้นหา 'git double dash'
หนาม̈

คำตอบ:


376

สมมติว่าฉันมีไฟล์ชื่อpath/to/file.txtในที่เก็บ Git ของฉันและฉันต้องการยกเลิกการเปลี่ยนแปลง

git checkout path/to/file.txt

ตอนนี้สมมติว่าไฟล์ชื่อmaster...

git checkout master

อ๊ะ! ที่เปลี่ยนสาขาแทน --แยกต้นไม้ที่คุณต้องการที่จะตรวจสอบจากไฟล์ที่คุณต้องการที่จะตรวจสอบ

git checkout -- master

นอกจากนี้ยังช่วยเราได้หาก freako บางคนเพิ่มไฟล์ชื่อ-fในที่เก็บของเรา:

git checkout -f      # wrong
git checkout -- -f   # right

นี้ถูกบันทึกไว้ในคอมไพล์เช็คเอาต์: อาร์กิวเมนต์ Disambiguation


12
สิ่งนี้เป็นจริงสำหรับคำสั่ง bash จำนวนมากไม่ใช่แค่คำสั่ง git ใช่ไหม
NHDaly

40
@NHDaly: ใช่มันเป็นความจริง อย่างไรก็ตามหมายเหตุคำศัพท์: "Bash" มีเพียงไม่กี่คำสั่ง (อาจจะประมาณ 20 หรือมากกว่านั้น) คำสั่งส่วนใหญ่เป็นโปรแกรมแยกต่างหากจาก Bash มันเป็นส่วนหนึ่งของมาตรฐาน POSIX ที่--สามารถใช้เพื่อแยกตัวเลือกจากอาร์กิวเมนต์อื่น ๆ ดังนั้นคุณจะเห็นมันในคำสั่งเช่นcpและmv(ซึ่งไม่ได้เป็นส่วนหนึ่งของ Bash)
Dietrich Epp

6
ความคิดใดว่าทำไมไวยากรณ์นี้ไม่ได้อธิบายอย่างถูกต้องในcheckoutเอกสารคำสั่ง?
TanguyP

4
@DietrichEpp ในหลาย ๆ ที่มันถูกระบุว่าเป็นพารามิเตอร์ที่เป็นไปได้สำหรับcheckoutคำสั่ง แต่ไม่มีที่ไหนที่เอกสารอธิบายสิ่งที่มันทำหรือทำไมมันใช้ ... ซึ่งเป็นสิ่งที่นำฉันมาที่นี่ในที่สุด
chris

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

109

เครื่องหมายขีดคั่นคู่ "-" หมายถึง "การสิ้นสุดของการตั้งค่าสถานะบรรทัดคำสั่ง" นั่นคือบอกให้คำสั่งก่อนหน้านี้ไม่ลองแยกวิเคราะห์สิ่งที่เกิดขึ้นหลังจากตัวเลือกบรรทัดคำสั่ง


2
เพื่อความชัดเจนgitมันมีความหมายมากกว่านี้ในขณะที่มันยังหมายถึงการโต้แย้งหลังจากที่--ไม่สามารถเป็นชื่อสาขาและโดยนัยการโต้แย้งก่อนที่--จะไม่สามารถเส้นทางไฟล์
Gem Taylor

0

โปรดทราบว่าคุณไม่จำเป็นต้องใช้เนื่องจาก Git 2.5 (Q2 2015) a ' --' ถ้าอาร์กิวเมนต์ของคุณมีอักขระตัวแทน ( *)

การแก้ปัญหาเพื่อช่วยให้การgit <cmd> <revs> <pathspec>ประชุมบรรทัดคำสั่ง "" เพื่อตรวจจับเส้นทางที่พิมพ์ผิดนั้นคือตรวจสอบให้แน่ใจว่าพารามิเตอร์ที่ไม่ใช่ rev ทั้งหมดในส่วนต่อมาของบรรทัดคำสั่งเป็นชื่อของไฟล์ในแผนผังการทำงาน แต่นั่นหมายความว่า " git grep $str -- \*.c" disambiguated กับ " --" เพราะไม่มีใครมีสติจะสร้างไฟล์ที่มีชื่ออย่างแท้จริงคือดอกจัน - ดอท - ซี

Git 2.5 สูญเสียการรู้สำนึกที่จะประกาศว่าด้วยสายอักขระตัวแทนผู้ใช้น่าจะหมายถึงการให้เส้นทางของเรา

git checkout 'a*'
# same as
git checkout -- 'a*'

ดูกระทำ 28fcc0b (2 พฤษภาคม 2015) โดยDuy เหงียน (nguyenlocduy )
(รวมโดยJunio C Hamano - gitster-ในการกระทำ 949d167ที่ 19 พฤษภาคม 2015)

pathspec: หลีกเลี่ยงความต้องการ " --" เมื่อใช้ไวด์การ์ด

เมื่อ--ขาด" " จากบรรทัดคำสั่งและคำสั่งสามารถใช้ทั้ง revs และพา ธ ได้แนวคิดก็คือถ้าอาร์กิวเมนต์สามารถถูกมองว่าเป็นทั้ง SHA-1 ที่ขยายออกและพา ธ ดังนั้น--จำเป็นต้องใช้" " หรือปฏิเสธที่จะดำเนินการต่อ
ปัจจุบันมีการใช้งานเป็น:

  • (1) ถ้ามีการโต้แย้งอาร์กิวเมนต์จะต้องไม่มีอยู่ใน worktree
  • (2) มิฉะนั้นจะต้องมีอยู่ใน worktree
  • (3) --จำเป็นต้องมี ""

กฎเหล่านี้ใช้ได้กับเส้นทางตัวอักษร แต่เมื่อเส้นทางที่ไม่ใช่ตัวอักษรมีส่วนเกี่ยวข้องนั้นผู้ใช้มักจะต้องเพิ่ม " --" เพราะมันล้มเหลว (2) และ (1) แทบไม่ได้พบกันจริง ๆ ( *.cเช่น "1") (1) พบถ้ามีการอ้างอิงชื่อ " *.c")

โปรแกรมปรับปรุงนี้แก้ไขกฎเล็กน้อยโดยพิจารณา*สัญลักษณ์ตัวแทน( ) wildsp pathspec ใด ๆ"มีอยู่ใน worktree"
กฎกลายเป็น:

  • (1) ถ้า arg เป็น rev แล้วจะต้องมีอยู่ใน worktree หรือไม่ใช่ pathspec ของ wildcard ที่ถูกต้อง
  • (2) มีอยู่ใน worktree หรือเป็น wildsp pathspec
  • (3) --จำเป็นต้องมี ""

ด้วยกฎใหม่ " --" ไม่จำเป็นต้องใช้เวลาส่วนใหญ่เมื่อมีการใช้สัญลักษณ์แทนพา ธ


ด้วย Git 2.26 (ไตรมาสที่ 1 ปี 2020) ตรรกะการแก้ความกำกวมในการบอกการแก้ไขและการแยกออกจากกันนั้นได้รับการปรับแต่งเพื่อให้อักขระพิเศษแบ็กสแลชที่หนีจากแบ็กสแลชไม่นับในกฎ

ดูกระทำ 39e21c6 (25 มกราคม 2020) โดยเจฟฟ์คิง (peff )
(รวมโดยJunio C Hamano - gitster-ในการกระทำ 341f8a6 , 12 กุมภาพันธ์ 2020)

verify_filename(): จัดการแบ็กสแลชในกฎ "wildcards is pathspecs"

รายงานโดย: David Burström
ลงนามโดย: Jeff King

กระทำ28fcc0b71a ( pathspec: หลีกเลี่ยงความต้องการ " --" เมื่อใช้ไวลด์การ์ด, 2015-05-02) ได้รับอนุญาต:

git rev-parse '*.c'

ไม่มีเส้นประ

แต่กฎที่ใช้ในการตรวจสอบสัญลักษณ์แทนกำลังมองหา glob พิเศษใด ๆ
นี่เป็นรูปแบบที่เสรีมากเกินไปซึ่งหมายความว่ารูปแบบที่ไม่ได้ใช้การจับคู่สัญลักษณ์แทนเช่น " a\b" จะถือว่าเป็นเส้นทาง

หากคุณมีไฟล์ดังกล่าวอยู่ในดิสก์นั่นอาจเป็นสิ่งที่คุณต้องการ
แต่ถ้าคุณทำไม่ได้ผลลัพธ์จะสับสน: แทนที่จะพูดว่า " there's no such path a\b" เราจะยอมรับอย่างเงียบ ๆ ว่าเป็นเส้นทางที่ไม่ตรงกับสิ่งใดมาก (หรืออย่างน้อยก็ไม่ใช่สิ่งที่คุณตั้งใจ)
การค้นหาเส้นทาง " a\*b" จะไม่ขยายการค้นหาเลย มันจะค้นหารายการเดียวเท่านั้น " a*b"

การกระทำนี้เป็นการสลับกฎเพื่อทริกเกอร์เฉพาะเมื่อ glob metacharacters จะขยายการค้นหาซึ่งหมายความว่าทั้งสองกรณีนี้จะรายงานข้อผิดพลาด (คุณยังสามารถแก้ปัญหาด้วยการใช้ " --" แน่นอนเราแค่กระชับ heuristic DWIM)

( DWIM: ทำในสิ่งที่ฉันหมายถึง )

โปรดทราบว่าเราไม่ได้ทดสอบคุณสมบัติดั้งเดิมใน28fcc0b71aเลย
ดังนั้นโปรแกรมแก้ไขนี้ไม่เพียง แต่ทดสอบสำหรับมุมของกรณีเหล่านี้ แต่ยังเพิ่มการทดสอบการถดถอยสำหรับลักษณะการทำงานที่มีอยู่

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