Ý nghĩa của dấu gạch ngang kiểm tra Git


274

Ý nghĩa của dấu gạch ngang kép trước tên tệp trong lệnh git này là gì?

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

Họ có bắt buộc không? Nó có tương đương với

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

24
Đó là một biểu hiện vỏ. Xem unix.stackexchange.com/questions/11376/ Cách
iltempo

15
@iltempo: Nó hơi khác với Git. Đối với Git, nó tách cây khỏi các đường dẫn, trong trường hợp cây và đường dẫn có thể trông giống nhau.
Dietrich Epp

@Dietrich_Epp. Tôi hiểu rồi. Cảm ơn đã làm rõ.
iltempo

Cũng được ghi lại trong stackoverflow.com/a/1192194/6309
VonC

3
Nó là một bản sao, nhưng bản sao này ít nhất có thể được kết nối bằng truy vấn 'git double dash'.
Thorn

Câu trả lời:


376

Giả sử tôi có một tệp có tên path/to/file.txttrong kho Git của mình và tôi muốn hoàn nguyên các thay đổi trên đó.

git checkout path/to/file.txt

Bây giờ giả sử rằng tập tin được đặt tên master...

git checkout master

Rất tiếc! Điều đó đã thay đổi chi nhánh thay thế. Cây --tách biệt bạn muốn kiểm tra từ các tập tin bạn muốn kiểm tra.

git checkout -- master

Nó cũng giúp chúng tôi nếu một số freako thêm một tệp có tên -fvào kho lưu trữ của chúng tôi:

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

Điều này được ghi lại trong git-checkout: Định hướng đối số .


12
Điều này đúng với nhiều lệnh bash, không chỉ các lệnh git, đúng không?
NHDaly

40
@NHDaly: Vâng, đó là sự thật. Tuy nhiên, một lưu ý thuật ngữ: "Bash" chỉ có một vài lệnh (có thể là 20 hoặc hơn), hầu hết các lệnh là các chương trình riêng biệt với Bash. Nó thực sự là một phần của tiêu chuẩn POSIX --có thể được sử dụng để tách các tùy chọn khỏi các đối số khác, vì vậy bạn sẽ thấy nó trên các lệnh như cpmv(không phải là một phần của Bash).
Dietrich Epp

6
Bất kỳ ý tưởng tại sao cú pháp này không được mô tả đúng trong checkouttài liệu lệnh?
TanguyP 17/03/2016

4
@DietrichEpp Ở một số nơi, nó được liệt kê giống như một tham số có thể có cho checkoutlệnh, nhưng không tài liệu nào giải thích nó làm gì hoặc tại sao nó được sử dụng ... đó là điều cuối cùng đưa tôi đến đây.
chris

7
@DietrichEpp Đúng, nhưng đã đọc cú pháp (và ví dụ) trước khi đến với Stack Overflow, tôi vẫn không hiểu tại sao một người sẽ không muốn sử dụng --. Là một người không đến từ nền tảng linux, điều đó không rõ ràng. Đối với tôi, nó dường như là một cú pháp cụ thể cho git, không có mô tả về mục đích chức năng của nó. Tôi nghĩ sẽ tốt hơn nếu có một mô tả ngắn như các tùy chọn khác, hoặc ít nhất là một liên kết đến trang man linux .
chris

109

Dấu gạch ngang kép "-" có nghĩa là "kết thúc cờ dòng lệnh", nghĩa là nó báo cho lệnh trước không cố phân tích những gì xuất hiện sau các tùy chọn dòng lệnh.


2
Để rõ ràng, trong gitnó có nghĩa nhiều hơn thế, vì nó cũng có nghĩa là đối số sau --không thể là tên nhánh và bằng cách ngụ ý đối số trước đó --không thể là đường dẫn tệp.
Gem Taylor

0

Lưu ý rằng bạn sẽ không cần, vì Git 2.5 (quý 2 năm 2015) ' --' nếu đối số của bạn bao gồm ký tự đại diện ( *)

Một heuristic để giúp git <cmd> <revs> <pathspec>quy ước dòng lệnh "" bắt các đường dẫn bị sai là đảm bảo tất cả các tham số không quay vòng trong phần sau của dòng lệnh là tên của các tệp trong cây làm việc, nhưng điều đó có nghĩa là " git grep $str -- \*.c" phải luôn luôn không rõ ràng với " --", bởi vì không ai có thể tạo ra một tệp có tên theo nghĩa đen là dấu hoa thị-dot-see.

Git 2.5 mất đi sự heuristic để tuyên bố rằng với một chuỗi ký tự đại diện, người dùng có thể có nghĩa là cung cấp cho chúng ta một đường dẫn .

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

Xem cam kết 28fcc0b (02 tháng 5 năm 2015) của Duy Nguyễn ( nguyenlocduy) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 949d167 , ngày 19 tháng 5 năm 2015)

pathspec: tránh sự cần thiết của " --" khi ký tự đại diện được sử dụng

Khi " --" thiếu từ dòng lệnh và một lệnh có thể mất cả vòng quay và đường dẫn, ý tưởng là nếu một đối số có thể được xem là cả SHA-1 mở rộng và đường dẫn, thì " --" được yêu cầu hoặc git từ chối tiếp tục.
Nó hiện đang được thực hiện như:

  • (1) nếu một đối số là rev, thì nó không được tồn tại trong worktree
  • (2) khác, nó phải tồn tại trong worktree
  • (3) khác, " --" là bắt buộc.

Các quy tắc này hoạt động cho các đường dẫn theo nghĩa đen, nhưng khi tham gia vào đường dẫn không theo nghĩa đen, hầu như luôn luôn yêu cầu người dùng thêm " --" vì nó thất bại (2) và (1) thực sự hiếm khi gặp (lấy " *.c", ví dụ: (1) được đáp ứng nếu có một ref có tên " *.c").

Bản vá này sửa đổi các quy tắc một chút bằng cách xem xét bất kỳ đường dẫn *ký tự đại diện hợp lệ ( ) "tồn tại trong worktree".
Các quy tắc trở thành:

  • (1) nếu một đối số là một rev, thì nó phải tồn tại trong worktree hoặc không phải là một pathspec ký tự đại diện hợp lệ.
  • (2) khác, nó tồn tại trong worktree hoặc là một pathspec ký tự đại diện
  • (3) khác, " --" là bắt buộc.

Với các quy tắc mới, " --" không cần thiết hầu hết thời gian khi tham gia pathspec ký tự đại diện.


Với Git 2.26 (Q1 2020), logic phân biệt để phân biệt các sửa đổi và đường dẫn đã được điều chỉnh sao cho các ký tự đặc biệt toàn cầu thoát khỏi dấu gạch chéo ngược không được tính trong quy tắc "ký tự đại diện là pathspec".

Xem cam kết 39e21c6 (ngày 25 tháng 1 năm 2020) của Jeff King ( peff) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 341f8a6 , ngày 12 tháng 2 năm 2020)

verify_filename(): xử lý dấu gạch chéo ngược trong quy tắc "ký tự đại diện là pathspecs"

Báo cáo: David Burström
Đã ký: Jeff King

Cam kết 28fcc0b71a ( pathspec: tránh sự cần thiết của " --" khi sử dụng ký tự đại diện, 2015-05 / 02):

git rev-parse '*.c'

không có dấu gạch ngang kép.

Nhưng quy tắc mà nó sử dụng để kiểm tra các ký tự đại diện thực sự tìm kiếm bất kỳ đặc biệt toàn cầu nào.
Điều này là quá tự do, vì nó có nghĩa là một mẫu không thực sự phù hợp với bất kỳ ký tự đại diện nào, như " a\b", sẽ được coi là một đường dẫn.

Nếu bạn có một tập tin như vậy trên đĩa, đó có lẽ là những gì bạn muốn.
Nhưng nếu bạn không, kết quả thật khó hiểu: thay vì nói " there's no such path a\b", chúng tôi sẽ lặng lẽ chấp nhận nó như một đường dẫn mà rất có thể không khớp với điều gì (hoặc ít nhất là không như bạn dự định).
Tương tự như vậy, tìm kiếm đường dẫn " a\*b" hoàn toàn không mở rộng tìm kiếm; nó sẽ chỉ tìm thấy một mục duy nhất, " a*b".

Cam kết này chuyển quy tắc chỉ kích hoạt khi các nhân vật siêu nhân toàn cầu sẽ mở rộng tìm kiếm, nghĩa là cả hai trường hợp đó sẽ báo lỗi (tất nhiên bạn vẫn có thể định hướng bằng cách sử dụng " --", tất nhiên, chúng tôi chỉ thắt chặt heuristic DWIM).

( DWIM: Làm những gì tôi muốn nói )

Lưu ý rằng chúng tôi đã không kiểm tra tính năng gốc trong 28fcc0b71a .
Vì vậy, bản vá này không chỉ kiểm tra các trường hợp góc này mà còn thêm kiểm tra hồi quy cho hành vi hiện có.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.