2011-12-01 30 views
7

Theo như tôi biết, khi bạn muốn hoàn tác một thứ gì đó trong Git, bạn phải tìm lệnh để hoàn tác bất cứ điều gì bạn đã làm và phát hành nó. Ví dụ, một cách trong số rất nhiều để hoàn tác một cam kết và thực hiện lại nó là để làm theo các ví dụ từ here,Tại sao không có hoàn tác/làm lại trong Git?

$ git commit ... 
$ git reset --soft HEAD^ 
$ edit 
$ git add .... 
$ git commit -c ORIG_HEAD 

Hoặc để lùi lại một kéo, bạn có thể làm theo hướng dẫn từ here,

$ git reset --hard 

Nhưng những lệnh này không nhất thiết phải làm việc thay thế cho nhau. Có một lý do tại sao Git không cho phép đơn giản hoàn tác và làm lại lệnh? Một cái gì đó để làm với triết lý đằng sau nó? Ngoài ra, tôi không có nhiều kinh nghiệm với các hệ thống điều khiển phiên bản khác, nhưng có bất kỳ hệ thống nào cung cấp một lệnh hoàn tác và làm lại đơn giản không?

+0

Tôi không chắc chắn, nhưng tôi nghĩ bạn có thể làm điều này bằng cách sử dụng 'git rebase'. Kiểm tra http://gitready.com/intermediate/2009/01/31/intro-to-rebase.html – gustavotkg

+2

Ý tưởng này là bạn thường không bao giờ muốn làm những điều khiến bạn mất đi một phần lịch sử. Hoàn tác một cam kết sẽ loại bỏ nó khỏi lịch sử, do đó thường không phải là điều bạn sẽ làm. – poke

+0

@poke Vâng, Adobe Photoshop, ví dụ, duy trì một lịch sử rộng lớn và vẫn cho phép bạn hoàn tác/làm lại. Tại sao Git không làm như vậy? – john

Trả lời

6

Có một số vấn đề với một khái niệm như:

  • Không phải tất cả các hoạt động có thể đảo ngược. Đôi khi điều này là bởi vì Git không ghi lại đủ thông tin để suy ra trạng thái trước đó - điều đó sẽ cực kỳ tốn kém nói chung. Đôi khi, đó là những thứ như git reset --hard hoặc git clean, phá hủy những thay đổi không được theo dõi. Để hoàn tác chúng, nó sẽ phải liên tục tự động sao lưu. Đôi khi điều này là do khái niệm hoàn tác không rõ ràng - như bản thân bạn đã chỉ ra, có nhiều cách để hoàn tác một cam kết.

  • Nếu một thao tác có thể đảo ngược và nó có liên quan đến một số loại lịch sử, thì việc hoàn tác/làm lại cũng có trong lịch sử hay chúng sẽ biến mất? Cam kết có nên được hoàn tác hay không bằng cách cài đặt lại hoặc bằng cách hoàn nguyên (tạo một cam kết khác để hủy nó)?

  • Nếu không đăng nhập mọi điều cuối cùng bạn làm, làm cách nào bạn biết hoạt động gần đây nhất là gì? Giả sử bạn đã thêm một tệp vào chỉ mục và đã tạo một nhánh. Không có hồ sơ nào trong số đó là đầu tiên.

Ngay cả khi mọi thứ đã được xác định rõ ràng, nó sẽ là một lượng công việc vô lý để thực hiện. Làm thế nào để bạn quyết định những gì tạo thành một hành động duy nhất? Một lệnh Git đơn lẻ có thể làm nhiều thứ. Có nên hoàn tác một bước, toàn bộ điều? Điều gì sẽ xảy ra nếu bạn chạy một lệnh zillion mỗi bước nhỏ và bạn muốn hoàn tác tất cả? Và nó phải là hoàn hảo, hoàn toàn hoàn hảo, vì đó là loại tính năng sẽ được sử dụng bởi những người dùng thiếu kinh nghiệm, những người sẽ không biết cách khôi phục từ bất kỳ sai lầm nào. Vì vậy, giống như Git cung cấp cho bạn các công cụ để làm mọi thứ, nó cung cấp cho bạn các công cụ để xem những gì bạn đã làm và tự hoàn tác mọi thứ nếu muốn.

Ngoài ra, đối với "làm lại", như bạn đã xác định trong câu hỏi của bạn, nó lặp lại một lệnh, không thực hiện lại thao tác gốc. Khi bạn redid một cam kết, nó là một khác nhau. Chạy lại lệnh trước là thứ mà các shell dòng lệnh được thiết kế để thực hiện. Git không cần phải tái tạo lại nó.

4

Trên thực tế ví dụ đầu tiên của bạn có thể được thực hiện với:

$ git commit ... 
$ edit 
$ git add ... 
$ git commit --amend 

ví dụ thứ hai của bạn nên được nhiều hơn như git reset --hard <hash>

Câu trả lời cho câu hỏi của bạn là nó có khả năng có thể, nhưng có nó là nhiều lái xe triết lý git có nghĩa là nó chưa được thực hiện. Về mặt lý thuyết, không có cách nào để nói liệu bạn có cam kết bằng cách tạo ra nó hay xóa một cái khác, nhưng bằng cách sử dụng reflog, có lẽ có thể ... đã không thực sự nghĩ về nó theo cách đó trước đây.

Tôi không nghĩ rằng 'hoàn tác' và 'làm lại' là một điều rất phổ biến trong kiểm soát nguồn mặc dù, nhưng sửa tôi nếu tôi sai.

EDIT: Bạn có thể sắp xếp một tập lệnh có thể thực hiện những gì bạn đang sử dụng sau khi đăng nhập - không chắc liệu có đủ thông tin ở đó hay không, nhưng có thể đáng thử.

1

git thực sự là nhiều công cụ nhỏ hoạt động trên kho lưu trữ, chỉ mục và thư mục làm việc, vì vậy nó không có phần 'cốt lõi' cho bất kỳ 'hoàn tác' nào.

Điều đó nói rằng nó có nhiều nhật ký khác nhau, chẳng hạn như reflog để bạn xem lại những gì đã được thực hiện.

Cuối cùng, theo quy ước, nhiều hành động git thường được coi là 'chỉ một chiều', nghĩa là, bạn sẽ không muốn bất kỳ ai công khai xem nó, vì vậy git cố gắng 'làm cho bạn đi vòng chặn 'khi ở nơi công cộng. Nếu bạn vẫn còn trong repo địa phương của bạn, bạn có thể sao lưu với các lệnh khác nhau nhưng hoàn tác toàn cầu không phải là một lệnh cung cấp thích hợp.

+0

'một chiều duy nhất' là một cách hay để suy nghĩ về nó, như một khi một cái gì đó trong hoàn tác hoang dã và làm lại trở nên nguy hiểm – MattJenko

0

Cùng với các nhận xét khác, tôi sẽ xem git stash. Nhiều lần tôi stash một số công việc, sửa chữa cái gì khác, sau đó unstash và tiếp tục. Hoặc cho một webapp, stash công việc đã hoàn thành và không được cam kết của tôi, làm mới trình duyệt, unstash, mở một tab mới, và sau đó so sánh hai qua lại để đảm bảo sửa lỗi liên quan đến UI không làm hỏng bất kỳ thứ gì khác.

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