Câu trả lời:
Bởi vì không có điểm nào (các lệnh khác đã cung cấp chức năng đó rồi) và nó làm giảm khả năng thực hiện sai một cách tình cờ.
Một "thiết lập lại cứng" cho một đường dẫn chỉ được thực hiện với git checkout HEAD -- <path>
(kiểm tra phiên bản hiện có của tệp).
Thiết lập lại mềm cho đường dẫn không có ý nghĩa.
Một thiết lập lại hỗn hợp cho một đường dẫn là những gì git reset -- <path>
làm.
git checkout -- <path>
không làm một thiết lập lại cứng; nó thay thế nội dung của cây làm việc bằng nội dung được dàn dựng. git checkout HEAD -- <path>
thực hiện thiết lập lại cứng cho một đường dẫn, thay thế cả chỉ mục và cây làm việc bằng phiên bản từ cam kết CHÍNH.
reset --hard
với một đường dẫn sẽ cung cấp phần còn thiếu này. Git đã mạnh đến mức "Chúng tôi không cho phép bạn làm điều này vì sự bảo vệ của chính bạn" không có nước: Có rất nhiều cách để làm điều sai "một cách tình cờ". Không có vấn đề nào dù sao khi bạn có git reflog
.
git reset --hard -- <path>
. Có trường hợp sử dụng hợp pháp cho nó.
Bạn có thể hoàn thành những gì bạn đang cố gắng sử dụng git checkout HEAD <path>
.
Điều đó nói rằng, thông báo lỗi được cung cấp không có ý nghĩa với tôi (vì nó git reset
hoạt động tốt trên các thư mục con) và tôi thấy không có lý do tại sao git reset --hard
không nên làm chính xác những gì bạn yêu cầu.
Câu hỏi làm thế nào đã được trả lời , tôi sẽ giải thích phần tại sao .
Vì vậy, git reset làm gì? Tùy thuộc vào các tham số được chỉ định, nó có thể làm hai việc khác nhau:
Nếu bạn chỉ định một đường dẫn, nó sẽ thay thế các tệp phù hợp trong chỉ mục bằng các tệp từ một cam kết (theo mặc định). Hành động này hoàn toàn không ảnh hưởng đến cây làm việc và thường được sử dụng như đối diện với git add.
Nếu bạn không chỉ định một đường dẫn, nó sẽ di chuyển đầu nhánh hiện tại đến một xác nhận đã xác định và cùng với đó , tùy ý đặt lại chỉ mục và cây làm việc về trạng thái của cam kết đó. Đây thêm hành vi được điều khiển bởi các tham số chế độ:
--soft : không chạm vào chỉ mục và cây làm việc.
--mixed (mặc định): đặt lại chỉ mục nhưng không phải cây làm việc.
--hard : đặt lại chỉ mục và cây làm việc.
Ngoài ra còn có các tùy chọn khác, xem tài liệu cho danh sách đầy đủ và một số trường hợp sử dụng.
Khi bạn không chỉ định một cam kết, nó sẽ mặc định là CHÍNH, vì vậy git reset --soft
sẽ không làm gì cả, vì đó là lệnh để di chuyển đầu đến CHÍNH (về trạng thái hiện tại). git reset --hard
mặt khác, có ý nghĩa do tác dụng phụ của nó, nó nói di chuyển đầu đến CHÍNH và đặt lại chỉ mục và cây làm việc thành CHÍNH.
Tôi nghĩ bây giờ nên rõ ràng tại sao hoạt động này không dành cho các tệp cụ thể - bản chất của nó là di chuyển đầu chi nhánh ở vị trí đầu tiên, đặt lại cây làm việc và chỉ mục là chức năng phụ.
git checkout
lệnh? Và thực hiện thiết lập lại để làm điều tương tự sẽ gây nhầm lẫn cho người dùng hơn nữa. Câu trả lời của tôi là --hard
tùy chọn đó không áp dụng cho các tệp cụ thể vì đây là chế độ để đặt lại nhánh, không phải đặt lại chỉ mục. Và thiết lập lại cây làm việc được đặt tên là thanh toán, như bạn có thể đọc trong các câu trả lời khác. Tất cả những thứ đó chỉ là một thiết kế tồi của giao diện người dùng của Git, IMHO.
git checkout
: git reset --
chỉ đặt chỉ mục, trong khi chỉ git checkout --
đặt cây làm việc?
Hãy chắc chắn rằng bạn đặt dấu gạch chéo giữa gốc hoặc ngược dòng (nguồn) và nhánh thực tế:
git reset --hard origin/branch
hoặc là
git reset --hard upstream/branch`
Có một lý do rất quan trọng đằng sau đó: các nguyên tắc checkout
vàreset
.
Theo thuật ngữ Git, thanh toán có nghĩa là "đưa vào cây làm việc hiện tại". Và với việc git checkout
chúng ta có thể lấp đầy cây làm việc với dữ liệu từ bất kỳ khu vực nào , là từ một cam kết trong kho lưu trữ hoặc các tệp riêng lẻ từ một cam kết hoặc khu vực tổ chức (đó là mặc định).
Đổi lại, git reset không có vai trò này. Như tên cho thấy, nó sẽ thiết lập lại ref hiện tại nhưng luôn có kho lưu trữ dưới dạng nguồn, độc lập với "Reach" (--soft, --mixed hoặc --hard).
Tóm tắt lại
Do đó, điều có thể hơi khó hiểu là sự tồn tại của git reset COMMIT -- files
"ghi đè ĐẦU" chỉ với một số tệp không có ý nghĩa!
Trong trường hợp không có lời giải thích chính thức, tôi chỉ có thể suy đoán rằng các nhà phát triển git thấy rằng đó reset
vẫn là tên tốt nhất của lệnh để loại bỏ các thay đổi được thực hiện cho khu vực tổ chức và, với nguồn dữ liệu duy nhất là kho lưu trữ, sau đó " hãy mở rộng chức năng "thay vì tạo một lệnh mới.
Vì vậy, bằng cách nào đó git reset -- <files>
đã có một chút đặc biệt: nó sẽ không ghi đè lên ĐẦU. IMHO tất cả các biến thể như vậy sẽ là ngoại lệ. Ngay cả khi chúng ta có thể hình dung một --hard
phiên bản, những người khác (ví dụ --soft
) sẽ không có ý nghĩa.
git reset -- <files>
đã giảm như được thêm vào bởi vì đây là tính năng hữu ích nhưng không ai chắc chắn nên đặt lệnh nào. May mắn thay, bây giờ chúng ta có nhiều git restore
chức năng lành mạnh hơn git checkout -- <path>
git checkout <commit> -- <path>
và git reset [<commit>] -- <path>
có nhiều mặc định hơn và thậm chí nhiều tính năng hơn bạn không thể làm trước đây (Trái với câu trả lời được chấp nhận nói. Bây giờ bạn cuối cùng có thể dễ dàng khôi phục cây chỉ hoạt động mà không cần chạm vào chỉ mục).
Các git reset
nhãn hiệu danh sách 3 cách gọi:
2 là file-khôn ngoan: Chúng không ảnh hưởng đến cây làm việc , nhưng chỉ hoạt động trên các tệp trong chỉ mục được chỉ định bởi <paths>
:
git reset [-q] [<tree-ish>] [--] <paths>..
git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
1 là cam kết khôn ngoan: Hoạt động trên tất cả các tệp trong tham chiếu <commit>
và có thể ảnh hưởng đến cây làm việc:
git reset [<mode>] [<commit>]
Không có chế độ gọi chỉ hoạt động trên các tệp được chỉ định và ảnh hưởng đến cây làm việc.
Nếu bạn muốn cả hai:
Bạn có thể sử dụng bí danh này trong tệp cấu hình git của mình:
[alias]
reco = !"cd \"${GIT_PREFIX:-.}\" && git reset \"$@\" && git checkout \"$@\" && git status --short #" # Avoid: "fatal: Cannot do hard reset with paths."
Sau đó, bạn có thể thực hiện một trong:
$ git reco <paths>
$ git reco <branch/commit> <paths>
$ git reco -- <paths>
(Mnenonic cho reco
: re
set && c
heck o
ut)
git checkout -- <path>
nên được thay thế bằnggit reset --hard <path>
. Nó có ý nghĩa hơn nhiều ...