Với Mercurial, làm cách nào để tôi có thể "nén" một loạt các bộ thay đổi thành một bộ trước khi đẩy?


96

Giả sử tôi có một kho lưu trữ Mercurial cục bộ và từ xa. Bây giờ, tôi bắt đầu làm việc trên một tính năng. Tôi làm việc trên nó và khi tôi nghĩ rằng nó đã xong, tôi cam kết các thay đổi. Kiểm tra nó thêm một chút, tôi thấy rằng tôi có thể cải thiện thêm tính năng này bằng cách điều chỉnh một số thứ trong mã. Tôi thực hiện thay đổi và cam kết. 20 phút sau, tôi phát hiện có một lỗi trong tính năng mới này, vì vậy tôi đã sửa nó và cam kết luôn.

Bây giờ tôi có 3 tập thay đổi mà tôi thực sự muốn đẩy vào kho lưu trữ từ xa dưới dạng một tập thay đổi với thông báo "Triển khai tính năng X", chẳng hạn.

Làm thế nào tôi có thể làm điều này mà không gặp nhiều rắc rối? Tôi tin rằng tôi có thể làm điều đó với các bản vá, nhưng có vẻ như rất nhiều việc.


40
Rõ ràng đây không phải là chỗ của tôi để nói bạn cố gắng nén các bộ thay đổi của mình, nhưng bạn có thể muốn xem xét rằng một nửa giá trị của kiểm soát phiên bản đang trả lời "tại sao" chứ không chỉ "cái gì" vài tháng và nhiều năm sau. Trình bày chính xác về cách một đối tượng địa lý ra đời và trong những giai đoạn nào, có thể có giá trị trong tương lai. Việc loại bỏ nó có vẻ rất ... không kiểm soát.
Ry4an Brase, 31-07-09

Điều này dẫn đến một câu hỏi khác ... Sự khác biệt giữa 'lịch sử' và 'sự sụp đổ'
sylvanaar

1
sập cung cấp một tập hợp con các tính năng của histedit và histedit có UX trực quan hơn nhiều.
Stefan Rusek

1
Nó cũng cung cấp một cơ chế để chỉnh sửa thông báo tập hợp các thay đổi đã hợp nhất.
Stefan Rusek

1
@ Ry4an: Trên thực tế, việc bóp méo / thu gọn có liên quan đến việc kiểm soát phiên bản trong một số trường hợp. Nếu không có vấn đề, tôi sẽ có hai cam kết mỗi ngày không liên quan đến các tính năng hoặc sửa lỗi, mà là để chuyển mã từ máy tính xách tay sang máy tính để bàn và ngược lại. Họ chỉ thêm nhiễu vào lịch sử phiên bản.
John Reynolds

Câu trả lời:


39

Làm thế nào về Phần mở rộng Thu gọn ?


20
Lời chào từ tương lai! Tôi chỉ googled cho cùng một chức năng và dường như ngày nay hg hỗ trợ điều này ra khỏi hộp với hg rebase --collapse. Kiểm tra wiki hg về lệnh rebase. Vì câu hỏi này là kết quả tìm kiếm tổng thể thứ 3 và là kết quả đầu tiên trên stackoverflow nên tôi nghĩ rằng thông tin đó có thể hữu ích.
a.peganz

1
Lời chào từ xa hơn nữa trong tương lai !! Phần mở rộng rebase dường như chỉ được nhắm mục tiêu vào việc chuyển các tập thay đổi từ nhánh này sang nhánh khác. Có, có một tùy chọn - thu gọn, nhưng dường như vẫn chỉ có thể áp dụng khi di chuyển một tập hợp các thay đổi qua các nhánh. Xem < thương
tiếc-scm.org/wiki/…

3
Bạn có thể sử dụng hg rebasevới --collapsetrong một nhánh duy nhất.
UuDdLrLrSs

52

Các histedit phần mở rộng là chính xác những gì bạn đang tìm kiếm.

hg histedit -o

hoặc là

hg histedit --outgoing

sẽ hiển thị danh sách các bộ thay đổi gửi đi. Từ danh sách bạn có thể

  • Gấp 2 hoặc nhiều tập thay đổi tạo một tập thay đổi duy nhất
  • Thả các tập thay đổi xóa chúng khỏi lịch sử
  • Sắp xếp lại các tập thay đổi theo cách bạn muốn.

histedit sẽ nhắc bạn về thông báo cam kết mới của các tập thay đổi đã gấp mà nó đặt mặc định cho hai thông báo với "\ n *** \ n" phân tách chúng.

Bạn cũng có thể nhận được kết quả tương tự bằng cách sử dụng phần mở rộng mq, nhưng khó hơn rất nhiều.

Bạn cũng có thể sử dụng tiện ích mở rộng thu gọn để thực hiện việc gấp, nhưng nó không cung cấp giao diện người dùng đẹp và không cung cấp cách chỉnh sửa thông báo cam kết kết quả. Việc chỉnh sửa thông báo cam kết kết quả cũng cho phép xóa thông báo cuối cùng, đây là thứ mà tôi luôn tận dụng.


cảm ơn, đó chính xác là những gì tôi cần. Sẽ rất tuyệt nếu bạn có thể làm điều đó từ bên trong TortoiseHg - nhưng dòng lệnh đủ đơn giản.
sylvanaar

21

Có, bạn có thể làm điều đó với các bản vá lỗi: Hãy giả sử công việc của bạn nằm trong các bộ thay đổi 100 đến 110, bao gồm

  1. Tạo một bản vá:

    % hg export -o mypatch 100:110 --git

  2. Cập nhật lên 99:

    % hg update 99

  3. Áp dụng bản vá với --no-commit (nếu không bạn sẽ lấy lại tất cả các tập tin thay đổi của mình):

    % hg import --no-commit mypatch

  4. Cam kết tất cả các thay đổi cùng một lúc:

    % hg commit

  5. Bây giờ bạn có hai đầu (110 và 111) tương đương nhau về các tệp mà chúng tạo ra trong thư mục làm việc của bạn - có thể khác biệt chúng cho rõ ràng trước khi loại bỏ các đầu cũ:

    % hg strip 100

Được rồi, bây giờ tôi đã đánh vần hết, nó có vẻ dài dòng, nhưng bản thân tôi đã làm nhiều lần, tôi không thấy nó là quá nhiều việc vặt ...


1
Câu trả lời tuyệt vời, nhưng có một điều kiện tiên quyết: tiện ích mở rộng MQ phải được bật .
Chris Kelly

Để bao gồm các thay đổi trong tệp nhị phân, hãy đảm bảo sử dụng tùy chọn --git: ví dụ: "hg export -o mypatch 100: 110 --git" Để biết thêm thông tin, vui lòng xem: stackoverflow.com/a/12537738/ 367663 Tôi có quyền tự do sửa đổi câu trả lời.
Kharlos Dominguez

1
Có vẻ quá phức tạp, tại sao không hg strip --keepvà sau đó cam kết mọi thứ trong một cam kết?
G. Demecki

@ G.Demecki Vì đó là một hoạt động có khả năng rất thua lỗ ..? Mặc dù MQ là quá mức cần thiết (và thậm chí không được khuyến khích), ngoại trừ khi mong muốn một quy trình làm việc như vậy.
user2864740

@ user2864740 Có thể bạn đúng, vì tôi không phải là chuyên gia về Mercurial. Nhưng theo mặc định, hg stripsẽ đặt một bản sao lưu trong .hg/strip-backup/thư mục. Tôi đoán nó không an toàn lắm git reflognhưng vẫn cung cấp một số loại cứu hộ.
G. Demecki

19

Nếu bạn đang sử dụng TortoiseHg, sử dụng có thể chỉ cần chọn hai bản sửa đổi (sử dụng CTRL để chọn những bản không tiếp theo), nhấp chuột phải và chọn "Nén Lịch sử" .

Sau đó, bạn sẽ nhận được một danh sách thay đổi mới trong đầu mới bắt đầu từ thay đổi đầu tiên bạn đã chọn trước đó, nó sẽ chứa tất cả các danh sách thay đổi hậu duệ giữa những thay đổi bạn đã chọn.

Bạn có thể đơn giản loại bỏ danh sách thay đổi cũ nếu bạn không cần chúng nữa: sử dụng tiện ích mở rộng MQ cho nó. Một lần nữa, trong TortoiseHg: nhấp chuột phải vào danh sách thay đổi đầu tiên cần được loại bỏ với tất cả các hậu duệ của nó, "Sửa đổi lịch sử -> Dải" .


18

Phương pháp sử dụng mq ưa thích của tôi cho lần gấp này là sử dụng TortoiseHg như được mô tả ở đây . Tuy nhiên, nó có thể dễ dàng được thực hiện từ dòng lệnh như sau:

hg qimport -r <first>:<last> 
    -- where <first> and <last> are the first and last changesets 
    -- in the range of revisions you want to collapse

hg qpop <first>.diff
    -- remove all except for the first patch from the queue
    -- note: mq names patches <#>.diff when it imports them, so we're using that here

hg qfold <next>.diff
    -- where <next> is <first>+1, then <first>+2, until you've reached <last>

hg qfinish -a
    -- apply the folded changeset back into the repository

(Có thể có một cách tốt hơn để thực hiện bước gấp đôi, nhưng tôi không biết về nó, vì tôi thường sử dụng TortoiseHg cho hoạt động đó.)

Thoạt đầu có vẻ hơi phức tạp, nhưng khi bạn đã bắt đầu sử dụng mq, nó khá đơn giản và tự nhiên - ngoài ra bạn có thể làm tất cả những thứ khác với mq mà có thể khá tiện dụng!


4

hg collapsehg histeditlà những cách tốt nhất. Hoặc, đúng hơn, sẽ là những cách tốt nhất, nếu chúng hoạt động đáng tin cậy ... Tôi đã gặp histeditsự cố với một kết xuất ngăn xếp trong vòng ba phút. Collapsekhông phải là tốt hơn nhiều.

Tôi nghĩ rằng tôi có thể chia sẻ hai BKM khác:

  1. hg rebase --collapse

    Phần mở rộng này được phân phối với Mercurial. Tôi vẫn chưa gặp vấn đề với nó. Bạn có thể phải chơi một số trò chơi để giải quyết các hg rebasehạn chế - về cơ bản, nó không thích phục hồi về tổ tiên trên cùng một nhánh, được đặt tên hoặc mặc định, mặc dù nó cho phép nếu khôi phục giữa các nhánh (được đặt tên).

  2. Di chuyển kho lưu trữ ( foo/.hg) đến thư mục làm việc ( bar) và các tệp của nó. Không phải hướng ngược lại.

Một số người đã nói về việc tạo hai cây sao chép và sao chép các tệp giữa chúng. Hoặc vá giữa chúng. Thay vào đó, nó dễ dàng hơn để di chuyển các .hgthư mục.

hg clone project work
... lots of edits
... hg pull, merge, resolve
hg clone project, clean
mv work/.hg .hg.work
mv clean/.hg work/.hg
cd work
... if necessary, pull, nerge, reconcile - but that would only happen because of a race
hg push

Điều này hoạt động miễn là các kho lưu trữ thực, .hgcây, độc lập với thư mục làm việc và các tệp của nó.

Nếu họ không độc lập ...


Trong năm 2015, histeditlà một lựa chọn rất tốt cho nhiệm vụ này. Tôi vẫn không tin tưởng nó khi tôi thực hiện git rebase -i, nhưng nó không bị lỗi .. ít nhất các phiên bản mới hơn sẽ để lại cho bạn một nhánh tạm thời nếu có gì đó sai khủng khiếp, vì vậy lần duy nhất các bộ thay đổi sẽ bị loại bỏ là sau khi nhánh mới được cam kết.
user2864740,

2

Tôi chưa bao giờ sử dụng Mercurial, nhưng điều này nghe rất giống những gì Martin Fowler đã nói trên blog của anh ấy cách đây không lâu:

http://martinfowler.com/bliki/MercurialSquashCommit.html


Điều đó trông có vẻ phức tạp hơn một chút, nhưng cảm ơn vì liên kết. Thành thật mà nói, tôi hy vọng một số tiện ích mở rộng kỳ diệu sẽ làm đúng những gì tôi muốn, giống như lấy và cấy ghép với các bộ thay đổi kéo và hái anh đào.
Lucas

0

Tại sao không chỉ hg strip --keeplệnh?

Sau đó, bạn có thể cam kết tất cả các thay đổi dưới dạng một cam kết.


@Strawberry không cung cấp câu trả lời ?? Nó nghĩ rằng nó hoàn toàn trả lời câu hỏi của tác giả. Bạn có thể giải thích quan điểm của bạn?
G. Demecki

Đó là lịch sử cổ đại, vì vậy tôi sẽ rút lại nhận xét - nhưng câu trả lời Được chấp thuận có vẻ giống như một tài liệu tham khảo có thẩm quyền hơn.
Strawberry

1
@Strawberry Quả thực đó là chủ đề cổ xưa. Nhưng câu trả lời được chấp nhận đã lỗi thời, vì Mercurial không còn cần phần mở rộng của bên thứ 3 riêng biệt cho công việc này.
G. Demecki

0

HistEdit sẽ làm những gì bạn muốn, nhưng nó có thể quá mức cần thiết. Nếu điều duy nhất bạn cần là gấp một số bộ thay đổi lại với nhau, thì Phần mở rộng Thu gọn sẽ thực hiện công việc.


1
mặc dù nó cung cấp giao diện người dùng dễ sử dụng và dễ hiểu hơn nhiều, đó là quá đủ lý do để sử dụng nó, nhưng nó cũng cung cấp một cơ chế để chỉnh sửa thông báo tập hợp các thay đổi đã hợp nhất, đây là một điều khác mà tôi luôn muốn làm khi hợp nhất các bộ thay đổi.
Stefan Rusek

Và vấn đề chỉ hiểu về giao diện người dùng thì người ta thực sự không hiểu .. Dù sao, trong quá khứ, trong khi lịch sử cho phép thay đổi 'mớ hỗn độn', cũng như thay đổi thông báo khi 'gấp'. Lịch sử là hoàn hảo; nếu bất cứ điều gì, phần mở rộng thu gọn là không hữu ích.
user2864740,

0

Giả sử bạn có hai cam kết chưa xuất bản THISTHATcam kết trong Mercurial và muốn chúng kết hợp thành một cam kết duy nhất tại THISđiểm ::

... --> THIS --> ... --> THAT --> ... --> LAST

Kiểm tra xem cam kết của bạn chưa được xuất bản ::

$ hg glog -r "draft() & ($THIS | $THAT)"

Cập nhật để LASTcam kết ::

$ hg up

và nhập các cam kết lên đến THISMQ ::

$ hg qimport $THIS::.

Bỏ áp dụng tất cả các bản vá và chỉ áp dụng trước THIS::

$ hg qpop -a
$ hg qpush
$ hg qapplied
... THIS ...

Tham gia với THAT::

$ hg qfold $THATNAME

LƯU Ý Để tìm cách THATNAMEsử dụng tên ::

$ hg qseries

Áp dụng tất cả các bản vá và chuyển chúng vào lịch sử kho lưu trữ ::

$ hg qpush -a
$ hg qfinish -a

Bài đăng trên blog của tôi về chủ đề là Tham gia hai cam kết trong Mercurial .


0

Có, strip --keephoạt động cho câu hỏi của Tác giả. Nhưng nó hơi khác so với những người khác, ví dụ, nếu bạn có phiên bản từ 1 đến 30 nhưng chỉ muốn thu gọn phiên bản 12-15. Các giải pháp khác hoạt động nhưng không strip --keep.

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.