Tôi nghĩ rằng gốc rễ của vấn đề là git (và điều khiển phiên bản thường) buộc bạn phải suy nghĩ về chuỗi các thay đổi, nhưng một changeset hoặc tính năng ngành hoặc bất cứ điều gì bạn gọi một nhóm liên kết các thay đổi có liên quan nói chung không theo thứ tự logic. Thứ tự trong đó mã được viết là ngẫu nhiên và không nhất thiết liên quan đến thứ tự mà nó được đọc.
Tôi không có giải pháp cho điều đó, nhưng tôi đã viết Perl script để giúp tự động hóa quá trình viết lại lịch sử. Nó tương tự như kịch bản Python của @MikaEloranta mà tôi chưa từng thấy khi tôi viết nó.
commit --fixup
và rebase --autosquash
rất tuyệt, nhưng chúng không đủ. Khi tôi có một chuỗi các cam kết A-B-C
và tôi viết thêm một số thay đổi trong cây đang hoạt động trong một hoặc nhiều cam kết hiện có, tôi phải xem lịch sử theo cách thủ công, quyết định những thay đổi nào trong đó cam kết, tạo giai đoạn và tạo các cam kết fixup!
. Nhưng git đã có quyền truy cập vào đủ thông tin để có thể làm tất cả những gì cho tôi.
Đối với mỗi đoạn trong git diff
, tập lệnh sử dụng git blame
để tìm cam kết chạm lần cuối vào các dòng có liên quan và gọi để thực hiện điều tương tự tôi đã thực hiện thủ công trước đây.
Nếu tập lệnh không thể phân giải một đoạn thành một cam kết đơn lẻ, rõ ràng, nó sẽ báo cáo nó như là một hunk thất bại và bạn sẽ phải quay trở lại phương pháp thủ công cho điều đó. Nếu bạn thay đổi một dòng hai lần trong hai cam kết riêng biệt, tập lệnh sẽ giải quyết một thay đổi trên dòng đó đến lần gần đây nhất của các cam kết đó, có thể không phải lúc nào cũng là độ phân giải chính xác. IMHO trong một chi nhánh "hình thức bình thường" chi nhánh bạn không nên thay đổi một dòng hai lần trong hai cam kết khác nhau, mỗi cam kết nên trình bày phiên bản cuối cùng của dòng mà nó chạm, để giúp người đánh giá (s). Tuy nhiên, nó có thể xảy ra trong một nhánh bugfix, để lấy ví dụ dòng foo(bar());
có thể được chạm vào bằng cam kết A (đổi tên foo
thành fox
) và cam kết B (đổi tên bar
thành baz
).
Nếu bạn thấy tập lệnh hữu ích, vui lòng cải thiện và lặp lại trên đó và có thể một ngày nào đó chúng tôi sẽ có được tính năng như vậy trong git
thích hợp. Tôi rất muốn nhìn thấy một công cụ có thể hiểu được một cuộc xung đột hợp nhất nên được giải quyết như thế nào khi nó được giới thiệu bởi một rebase tương tác.
Tại sao một yêu cầu kỳ lạ mà fixA phải được hợp nhất trong A? –
bởi vì nó phải có trong A ở nơi đầu tiên. – elmarco
Tôi cũng làm như vậy; Tôi không chắc tại sao mọi người nghĩ nó lạ. Nếu bạn đang cố gắng tổ chức các cam kết thành các phần nhỏ, được nhóm logic, thì sẽ tự nhiên khi chuẩn bị một số cam kết chưa được phát hành cùng một lúc. (Bạn có thể không biết nếu bạn đang thực sự thực hiện với A cho đến khi bạn hoàn thành C). – andy