2015-11-06 16 views

Trả lời

4

Cam kết đã sửa đổi không khác với bất kỳ cam kết nào khác. Theo nghĩa đó, hoàn toàn có thể khác biệt giữa cam kết 'bình thường' và một cam kết đã được sửa đổi.

Nói cách khác, git lưu các cam kết đã sửa đổi trong lịch sử ở đâu đó?

Không có danh sách nào chứa tất cả các cam kết đã được sửa đổi, không. Các cam kết sửa đổi có trong lịch sử giống như tất cả các cam kết khác.

Khi bạn sửa đổi một cam kết, về cơ bản nó sẽ bị loại bỏ và thay thế bằng một cái mới (nó cũng nhận được một băm mới) có những thay đổi từ cam kết ban đầu + thay đổi sửa đổi.

Trong số git reflog bạn có thể xem các hành động gần đây của mình và điều đó hiển thị sửa đổi các cam kết. Tài liệu tham khảo từ đó có thể được sử dụng để ví dụ hoàn tác git commit --amend. Xem thêm How to undo "git commit --amend" done instead of "git commit" để biết thêm chi tiết về điều đó.

+1

OK, cảm ơn Tim, _git reflog_ -> _git diff commit1_hash modify_commit_hash_ đã giải quyết được sự cố của tôi! –

0

Tôi không nghĩ rằng tôi hiểu câu hỏi, nhưng tôi nghĩ rằng một phần trong số đó là bởi vì tôi nghĩ rằng bạn có ý tưởng sai về những gì git commit --amend làm.

Cam kết, trong git, thực sự không thể thay đổi được. Tất cả những gì git commit --amend làm là viết mới cam kết với ID cha mẹ được cố ý thay đổi.

Hãy xem quy trình bình thường để thực hiện một cam kết mới.

Trước khi bạn thực hiện cam kết mới, bạn sửa đổi một số tệp trong cây công việc của mình, sau đó bạn sử dụng git add để thực hiện các thay đổi này để các phiên bản mới của tệp sẽ được cam kết. Điều này git add đặt phiên bản mới của tệp vào "chỉ mục" của git, tức là khu vực dàn dựng của nó.

Các tệp đã có trong cam kết trước đó đã có trong khu vực dàn dựng. Vì vậy, cam kết mới bạn sẽ thực hiện sẽ có tất cả các tệp gốc, ngoại trừ bất kỳ điều gì bạn đã thay đổi và sau đó git add -ed sẽ là phiên bản mới thay vì phiên bản cũ.

Bây giờ bạn chạy git commit (không --amend) và git nào sau đây:

  • thu thập một cam kết thông báo (từ -m, -F, hoặc chạy soạn thảo của bạn);
  • lấy tên và email của bạn và thời gian hiện tại;
  • lấy ID SHA-1 của cam kết hiện tại (không phải là số mới);
  • sử dụng vùng dàn để viết đối tượng "cây": đây là cây nguồn sẽ được liên kết với cam kết mới;
  • tạo đối tượng cam kết với tất cả thông tin này (author + committer, tree, ID cha và thông báo của bạn) —đây là đối tượng cam kết mới có ID SHA-1 duy nhất mới;
  • và cuối cùng, ghi ID mới vào chi nhánh, để nhãn nhánh trỏ đến ID mới thay vì những gì đã từng là nhánh nổi bật nhất.

Bước cuối cùng "phát triển các chi nhánh", do đó nếu bạn đã từng có một số cam kết, một cái gì đó như thế này:

... <- E <- F <- G <-- master 

bạn bây giờ có thêm một:

... <- E <- F <- G <- H <-- master 

Các tên chi nhánh (master hoặc bất kỳ tên nào có thể) bây giờ trỏ đến cam kết mới nhất của bạn HH chỉ lại những gì sử dụng làm cam kết mới nhất của bạn G.

Nếu bạn sử dụng git commit --amend, git thay đổi chuỗi này chỉ một chút nhỏ trong trường hợp này, F):

   G 
      /
... <- E <- F <- H <-- master 

Bây giờ master (hoặc bất kỳ chi nhánh bạn đang ở trên) điểm để H, mà điểm đến F, và vân vân.

Nếu bạn chạy git log, git bắt đầu bằng cam kết hiện tại (H) và ghi nhật ký, sau đó di chuyển đến cấp độ gốc (F) và ghi nhật ký, v.v. Cam kết G dường như đã biến mất.

ID SHA-1 cho G vẫn còn xung quanh (trong 30 ngày theo mặc định), trong "reflog". Có một reflog cho HEAD và một cho chi nhánh hiện tại của bạn. Nếu bạn đang ở trên chi nhánh master và bạn vừa thực hiện H, thì [email protected]{1} là mũi trước của master, cam kết G. Hoặc, nếu bạn có ID SHA-1 được lưu ở đâu đó trên màn hình, bạn có thể cắt và dán nó để xem cam kết G.

(Công tắc --amend cũng có thể sửa đổi cam kết hợp nhất. Điều này hoạt động chính xác như trên, điều đó có nghĩa là git phải sao chép tất cả ID cha từ nhánh nhánh cũ sang thẻ mới.)

Các vấn đề liên quan