Mercurial: làm thế nào để sửa đổi cam kết cuối cùng?


211

Tôi đang tìm kiếm một phần đối git commit --amendnghịch trong Mercurial, tức là một cách để sửa đổi cam kết mà bản sao làm việc của tôi được liên kết đến. Tôi chỉ quan tâm đến cam kết cuối cùng, không phải là một cam kết trước đó tùy tiện.

Các yêu cầu cho thủ tục sửa đổi này là:

  • nếu có thể, nó không nên yêu cầu bất kỳ phần mở rộng. Nó không được yêu cầu các tiện ích mở rộng không mặc định , tức là các tiện ích mở rộng không đi kèm với bản cài đặt Mercurial chính thức.

  • nếu cam kết sửa đổi là một đầu của chi nhánh hiện tại của tôi, thì không có đầu mới nào được tạo. Nếu cam kết không phải là đầu, một đầu mới có thể được tạo.

  • thủ tục phải an toàn theo cách mà nếu vì bất kỳ lý do gì việc sửa đổi không thành công, tôi muốn có cùng một bản sao làm việc và trạng thái kho lưu trữ được khôi phục như trước khi sửa đổi. Nói cách khác, nếu bản sửa đổi có thể thất bại, cần có một quy trình không an toàn để khôi phục trạng thái bản sao và kho lưu trữ đang hoạt động. Tôi đang đề cập đến "các lỗi" nằm trong bản chất của quy trình sửa đổi (ví dụ như xung đột), không phải là các vấn đề liên quan đến hệ thống tệp (như hạn chế truy cập, không thể khóa tệp để viết, ... )

Cập nhật (1):

  • thủ tục phải tự động hóa , do đó máy khách GUI có thể được thực hiện mà không cần bất kỳ tương tác người dùng nào.

Cập nhật (2):

  • các tệp trong thư mục làm việc không được chạm vào (có thể có các khóa hệ thống tệp trên các tệp đã sửa đổi nhất định). Điều này đặc biệt có nghĩa là, một cách tiếp cận khả thi có thể không cần phải có một thư mục làm việc sạch.

Câu trả lời:


289

Với việc phát hành Mercurial 2.2 , bạn có thể sử dụng --amendtùy chọn hg commitđể cập nhật cam kết cuối cùng với thư mục làm việc hiện tại

Từ tham chiếu dòng lệnh :

Cờ --amend có thể được sử dụng để sửa đổi cha mẹ của thư mục làm việc với một cam kết mới có chứa các thay đổi trong cha mẹ ngoài những thay đổi hiện được báo cáo bởi trạng thái hg, nếu có. Cam kết cũ được lưu trữ trong gói sao lưu trong .hg / dải sao lưu (xem gói trợ giúp hg và hg giúp giải quyết cách khôi phục nó).

Tin nhắn, người dùng và ngày được lấy từ cam kết sửa đổi trừ khi được chỉ định. Khi một thông báo không được chỉ định trên dòng lệnh, trình soạn thảo sẽ mở với thông báo về cam kết đã sửa đổi.

Điều tuyệt vời là cơ chế này "an toàn", bởi vì nó dựa vào tính năng "Các giai đoạn" tương đối mới để ngăn chặn các cập nhật sẽ thay đổi lịch sử đã được cung cấp bên ngoài kho lưu trữ cục bộ.


2
Câu trả lời tốt! Phần mở rộng phát triển thử nghiệm cho phép bạn sửa đổi các cam kết không phải đầu một cách an toàn . Các cam kết cũ sẽ được đánh dấu lỗi thời và ẩn. Với một máy chủ không xuất bản, bạn thậm chí có thể thực hiện việc này một cách an toàn sau khi bạn đã đẩy các thay đổi.
Martin Geisler

5
Để chỉ cập nhật tin nhắn vào lần xác nhận cuối cùng: hg commit --amend -m "đây là tin nhắn mới của tôi"
Jay Sheth

52

Bạn có 3 tùy chọn để chỉnh sửa các xác nhận trong Mercurial:

  1. hg strip --keep --rev -1hoàn tác (1) cam kết cuối cùng, vì vậy bạn có thể thực hiện lại (xem câu trả lời này để biết thêm thông tin).

  2. Sử dụng tiện ích mở rộng MQ , được cung cấp cùng với Mercurial

  3. Ngay cả khi nó không được vận chuyển với Mercurial, phần mở rộng Histedit đáng được đề cập

Bạn cũng có thể xem trên trang Lịch sử chỉnh sửa của wiki Mercurial.

Nói tóm lại, lịch sử chỉnh sửa thực sự khó khăn và nản lòng . Và nếu bạn đã thúc đẩy các thay đổi của mình, bạn hầu như không thể làm gì, ngoại trừ nếu bạn có toàn quyền kiểm soát tất cả các bản sao khác.

Tôi không thực sự quen thuộc với git commit --amendlệnh này, nhưng AFAIK, Histedit là cách tiếp cận gần nhất, nhưng thật đáng buồn là nó không được vận chuyển với Mercurial. MQ thực sự phức tạp để sử dụng, nhưng bạn có thể làm gần như mọi thứ với nó.


1
Tôi không chắc tại sao tôi lại bỏ lỡ rollback, nhưng dường như nó làm (gần như) những gì tôi muốn. Vấn đề duy nhất là, khi một tệp đã bị xóa cho cam kết ban đầu của tôi và nó đã được phục hồi cho cam kết đã sửa đổi của tôi: trước khi khôi phục, nó sẽ bị đảo ngược, sau khi khôi phục, nó sẽ được lên lịch để xóa (nhưng tệp vẫn tồn tại trong thư mục làm việc)
mstrap

@Marc Tôi không chắc là tôi hiểu vấn đề của bạn, nhưng hãy xem lệnh quên, tôi nghĩ đó là những gì bạn đang tìm kiếm.
krtek

Tôi không nghĩ "quên" sẽ hữu ích ở đây. Đây là vấn đề chi tiết hơn: (1) Tôi đang ở phiên bản 2 (2) Xóa "tệp" và có một số thay đổi khác (3) Cam kết thay đổi, dẫn đến sửa đổi 3 (4) Bây giờ tôi sẽ thay đổi quyết định và quyết định "tập tin" không nên bị xóa khỏi cam kết, vì vậy tôi muốn sửa đổi bản sửa đổi 3. Do đó, tôi sẽ thêm lại "tập tin" hiện không được đảo ngược (5) Bây giờ tôi thực hiện khôi phục: nó sẽ thiết lập lại sự khao khát và đánh dấu " tập tin "như đã xóa. (6) Khi thực hiện lại "hg commit", "tập tin" sẽ vẫn bị xóa, mặc dù vậy nó không còn nữa. Làm thế nào một sửa chữa tự động cho trông như thế nào?
mstrap

1
Đối với phần tự động tôi không biết, nhưng bạn có thể làm hg revert myfileđể hoàn tác xóa. Có thể thêm lại với hg addcác tập tin sau khi rollbackcũng hoạt động.
krtek

3
Tôi đồng ý rằng nên tránh lịch sử chỉnh sửa các thay đổi đã xuất bản, nhưng chỉnh sửa lịch sử địa phương của tôi là một trong những điểm nổi bật của DVCS. MQ với qimport của nó là chỉnh sửa lịch sử thuần túy, AFAICT.
mstrap

38

GUI tương đương với hg commit --amend:

Điều này cũng hoạt động từ GUI của TortoiseHG (Tôi đang sử dụng v2,5):

Chuyển sang chế độ xem 'Cam kết' hoặc, trong chế độ xem bàn làm việc, chọn mục nhập 'thư mục làm việc'. Nút 'Cam kết' có một tùy chọn có tên 'Sửa đổi sửa đổi hiện tại' (nhấp vào mũi tên thả xuống của nút để tìm thấy nó).

nhập mô tả hình ảnh ở đây

          ||
          ||
          \/

nhập mô tả hình ảnh ở đây

Trống rỗng :

Tùy chọn bổ sung này sẽ chỉ được bật nếu phiên bản đồng bóng ít nhất là 2.2.0 và nếu bản sửa đổi hiện tại không công khai, không phải là bản vá và không có con. [...]

Nhấp vào nút sẽ gọi 'cam kết --amend' để 'sửa đổi' bản sửa đổi.

Thông tin thêm về điều này trên kênh dev THG


Rất hữu ích, cảm ơn. THG đủ thông minh để mặc định thông điệp cam kết (sửa đổi) thành thông điệp từ cam kết trước - đúng như những gì tôi muốn.
UuDdLrLrSs

7

Tôi đang điều chỉnh những gì krtek đã viết. Cụ thể hơn là giải pháp 1:

Giả định:

  • bạn đã cam kết một (!) thay đổi nhưng chưa đẩy nó
  • bạn muốn sửa đổi tập thay đổi này (ví dụ: thêm, xóa hoặc thay đổi tệp và / hoặc thông báo cam kết)

Giải pháp:

  • sử dụng hg rollbackđể hoàn tác cam kết cuối cùng
  • cam kết một lần nữa với những thay đổi mới tại chỗ

Các rollback thực sự hoàn tác các hoạt động cuối cùng. Cách làm việc của nó khá đơn giản: các hoạt động bình thường trong HG sẽ chỉ nối vào các tệp; điều này bao gồm một cam kết. Mercurial theo dõi độ dài tệp của giao dịch cuối cùng và do đó có thể hoàn toàn hoàn tác một bước bằng cách cắt các tệp trở lại độ dài cũ của chúng.


1
Cảm ơn cho giải pháp điều chỉnh (1); chỉ còn một vấn đề nhỏ với rollback, vui lòng xem nhận xét của tôi tại giải pháp của krtek.
mstrap

8
Một điều cần nhấn mạnh về rollback, bởi vì nó thu hút mọi người, đó là giao dịch cuối cùng trên repo được khôi phục, không phải là cam kết cuối cùng. Vì vậy, nếu một cái gì đó khác đã gây ra một ghi vào repo, rollback sẽ không giúp đỡ. Đó là một điều tinh tế nhưng quan trọng cần nhớ. MQ và histedit có thể giúp một khi cửa sổ rollback đã được đóng, nhưng vẫn chỉ đến một điểm nhất định.
Paul S

7

Giả sử rằng bạn chưa tuyên truyền những thay đổi của mình, đây là những gì bạn có thể làm.

  • Thêm vào .hgrc của bạn:

    [extensions]
    mq =
    
  • Trong kho của bạn:

    hg qimport -r0:tip
    hg qpop -a
    

    Tất nhiên, bạn không cần phải bắt đầu với sửa đổi zero hoặc pop tất cả các bản vá, cho lần cuối cùng chỉ có một pop ( hg qpop) đủ (xem bên dưới).

  • xóa mục nhập cuối cùng trong .hg/patches/seriestệp hoặc các bản vá bạn không thích. Sắp xếp lại là có thể quá.

  • hg qpush -a; hg qfinish -a
  • xóa các .difftệp (bản vá chưa được áp dụng) vẫn còn trong .hg / bản vá (nên là một trong trường hợp của bạn).

Nếu bạn không muốn để lấy lại tất cả các bản vá của bạn, bạn có thể chỉnh sửa nó bằng cách sử dụng hg qimport -r0:tip(hoặc tương tự), sau đó chỉnh sửa các công cụ và sử dụng hg qrefreshđể hợp nhất các thay đổi vào các bản vá trên cùng trên stack của bạn. Đọc hg help qrefresh.

Bằng cách chỉnh sửa .hg/patches/series, bạn thậm chí có thể xóa một số bản vá hoặc sắp xếp lại một số. Nếu lần sửa đổi cuối cùng của bạn là 99, bạn chỉ có thể sử dụng hg qimport -r98:tip; hg qpop; [edit series file]; hg qpush -a; hg qfinish -a.

Tất nhiên, thủ tục này rất nản lòng và rủi ro . Tạo một bản sao lưu của tất cả mọi thứ trước khi bạn làm điều này!

Là một sidenote, tôi đã thực hiện nó hàng trăm lần trên các kho lưu trữ chỉ riêng tư.


Tôi cũng đã cân nhắc sử dụng phần mở rộng mq, tuy nhiên nó đòi hỏi khá nhiều thao tác mà một số trong số chúng có thể thất bại (ví dụ: nếu các tệp nhị phân có liên quan). Hơn nữa, việc chỉnh sửa .hg / patch / series sẽ không được chấp nhận, vì quy trình này nên được sử dụng trong máy khách GUI (tôi đã cập nhật các yêu cầu ở trên)
mstrap

Hmmm, xin lỗi vì điều này sẽ không phù hợp với bạn, trên một kho lưu trữ riêng, điều này thực sự gây khó chịu (với các bản sao lưu - Tôi đã phá hủy một đại diện với nó rồi ^^). Thật tuyệt khi kết hợp các bản vá thành một trước khi đẩy các thay đổi cục bộ bằng cách sử dụng hg qfold, btw
hochl

+1 để sử dụng MQ, nhưng tôi nghĩ bạn đã quá nhiệt tình. Anh ta chỉ hỏi về việc sửa đổi cam kết cuối cùng. Ngoài ra, quá trình nhập sẽ kết thúc ngay sau khi kết hợp. 'Qimport -r tip; <chỉnh sửa nội dung>; qrefresh -e; qfin -a 'sẽ thực hiện công việc (-e để chỉnh sửa thông điệp cam kết)
Paul S

đúng, hợp nhất là một vấn đề, tôi thường chỉ bật một bản vá và sử dụng hg import -r<prev>:tip. Một điều đáng tiếc là không có lối tắt cho phiên bản trước, như trong lật đổ.
hochl

2

Các phiên bản gần đây của Mercurial bao gồm evolvephần mở rộng cung cấp hg amendlệnh. Điều này cho phép sửa đổi một cam kết mà không làm mất lịch sử sửa đổi trước trong kiểm soát phiên bản của bạn.

hg sửa đổi [TÙY CHỌN] ... [TẬP TIN] ...

bí danh: làm mới

kết hợp một bộ thay đổi với các bản cập nhật và thay thế nó bằng một bản mới

Commits a new changeset incorporating both the changes to the given files
and all the changes from the current parent changeset into the repository.

See 'hg commit' for details about committing changes.

If you don't specify -m, the parent's message will be reused.

Behind the scenes, Mercurial first commits the update as a regular child
of the current parent. Then it creates a new commit on the parent's
parents with the updated contents. Then it changes the working copy parent
to this new combined changeset. Finally, the old changeset and its update
are hidden from 'hg log' (unless you use --hidden with log).

Xem https://www.mercurial-scm.org/doc/evolution/user-guide.html#example-3-amend-a-changeset-with-evolve để biết mô tả đầy đủ về evolvetiện ích mở rộng.


Sử dụng lại cùng một thông điệp cam kết là một tính năng hay!
mở

1

Có thể không giải quyết được tất cả các vấn đề trong câu hỏi ban đầu, nhưng vì đây dường như là bài đăng thực tế về cách thức đồng bóng có thể sửa đổi cho cam kết trước đó, tôi sẽ thêm thông tin trị giá 2 xu của mình.

Nếu bạn giống tôi và chỉ muốn sửa đổi thông báo cam kết trước đó (sửa lỗi chính tả, v.v.) mà không cần thêm bất kỳ tệp nào, điều này sẽ hoạt động

hg commit -X 'glob:**' --amend

Không có bất kỳ mẫu bao gồm hoặc loại trừ nào hg committheo mặc định sẽ bao gồm tất cả các tệp trong thư mục làm việc. Áp dụng mẫu -X 'glob:**'sẽ loại trừ tất cả các tệp có thể, chỉ cho phép sửa đổi thông điệp cam kết.

Về mặt chức năng, nó giống như git commit --amendkhi không có tệp trong chỉ mục / giai đoạn.


0

Một giải pháp khác có thể là sử dụng uncommitlệnh để loại trừ tệp cụ thể khỏi cam kết hiện tại.

hg uncommit [file/directory]

Điều này rất hữu ích khi bạn muốn giữ cam kết hiện tại và bỏ chọn một số tệp khỏi cam kết (đặc biệt hữu ích cho việc files/directoriesđã bị xóa).

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.