Tại sao git không thể thiết lập lại cứng / mềm theo đường dẫn?


137

$ git reset -- <file_path> có thể thiết lập lại theo đường dẫn.

Tuy nhiên, $ git reset (--hard|--soft) <file_path>sẽ báo cáo một lỗi như dưới đây:

Cannot do hard|soft reset with paths.

Câu trả lời:


142

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.


72
Cá nhân, tôi nghĩ git checkout -- <path>nên được thay thế bằng git reset --hard <path>. Nó có ý nghĩa hơn nhiều ...
vergenzt

24
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.
Dan Fabulich

1
@EdPlunkett Er, câu thứ hai trong câu trả lời cho bạn biết lệnh nào khác cung cấp chức năng.
Amber

16
-1: Thanh toán cho sửa đổi đã nói sẽ không xóa các tệp khỏi bản sao làm việc nếu sửa đổi nói có chứa các tệp bị xóa. reset --hardvớ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.
void.pulum

1
như được đề cập bởi @ void.pulum thanh toán sẽ không xóa các tệp. Nếu bạn muốn hành vi đó thì nhìn vào câu trả lời này . Tuy nhiên, tôi hy vọng một ngày nào đó chúng ta sẽ nhận được git reset --hard -- <path>. Có trường hợp sử dụng hợp pháp cho nó.
Mariusz Pawelski

18

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 resethoạ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 --hardkhông nên làm chính xác những gì bạn yêu cầu.


sử dụng giai đoạn kiểm tra các thay đổi, không giống như thiết lập lại --soft
worc

11

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 --softsẽ 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 --hardmặ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 đặ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ụ.


Rõ ràng rằng thiết lập lại được dự định để di chuyển đầu chi nhánh ở vị trí đầu tiên, nhưng vì nó có chức năng bổ sung để đặt lại cây làm việc và chỉ mục cho toàn bộ các cam kết và chức năng đặt lại chỉ mục cho các tệp cụ thể, tại sao không Có chức năng đặt lại cây làm việc cho các tệp cụ thể không? Tôi tin rằng đó là những gì OP đang yêu cầu.
Danilo Souza Morães

Có lẽ bởi vì chức năng đó (đặt lại cây làm việc cho các tệp cụ thể) đã có sẵn dưới dạng git checkoutlệ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à --hardtù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.
người dùng

So sánh tùy chọn đầu tiên với git checkout: git reset --chỉ đặt chỉ mục, trong khi chỉ git checkout --đặt cây làm việc?
seeker_of_bacon

4

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`

Xin vui lòng đọc lại câu hỏi.
Xerus

3

Có một lý do rất quan trọng đằng sau đó: các nguyên tắc checkoutreset .

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 checkoutchú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ônkho 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

  • kiểm tra : Từ bất cứ đâu (index / repo commit) -> cây làm việc
  • đặt lại : Cam kết Repo -> Ghi đè ĐẦU (và tùy chọn chỉ mục và cây làm việc)

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 đó resetvẫ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 --hardphiên bản, những người khác (ví dụ --soft) sẽ không có ý nghĩa.


Tôi thích câu trả lời này. Thực sự, 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 restorechức năng lành mạnh hơn git checkout -- <path> git checkout <commit> -- <path>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).
Mariusz Pawelski

0

Giải trình

Các git resetnhã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>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 ảnh hưởng đến cây làm việc.

Giải pháp thay thế

Nếu bạn muốn cả hai:

  • Đặt lại phiên bản chỉ mục / bộ đệm của tệp (s)
  • Kiểm tra (các) tệp (nghĩa là làm cho cây làm việc khớp với chỉ mục và phiên bản cam kết)

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: reset && check out)


-2

git reset --soft HEAD ~ 1 tên tệp hoàn tác cam kết nhưng các thay đổi vẫn ở trạng thái cục bộ. tên tệp có thể - cho tất cả các tệp được cam kết


6
gây tử vongCannot do soft reset with paths.
alt
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.