git rebase sau khi hợp nhất git trước đó


79

Tôi có tình huống sau:

  • Tôi đã tạo một clone(Y) từ kho lưu trữ chính (X), bởi vì có nhiều người làm việc trên Y, chúng tôi không làm bất kỳ điều gì rebasemà chỉ làm merges. Khi chúng tôi muốn giao ( push) Y cho X, chúng tôi muốn làm điều đó rebaseđể mọi thứ đẹp đẽ và sạch sẽ

Vấn đề là khi thực hiện, rebasechúng tôi được yêu cầu thực hiện tất cả các hợp nhất mà chúng tôi đã làm ở các mergebước trước . Có giải pháp nào cho điều này, bên cạnh giải pháp có nghĩa là thực sự thực hiện lại việc hợp nhất?

Tôi hy vọng nó sẽ khá đơn giản vì chúng tôi đã giải quyết các hợp nhất xung đột.


Tại: "Bởi vì có nhiều người làm việc trên Y, chúng tôi không làm bất kỳ rebase mà chỉ hợp nhất", ý bạn là hợp nhất với ngược dòng là nó?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Câu trả lời:


82

Việc khôi phục để có được một lịch sử "sạch" được đánh giá quá cao. Cách tốt nhất nếu bạn muốn lưu giữ lịch sử là thực hiện hợp nhất thay vì tái cơ sở. Bằng cách đó, nếu bạn đã bao giờ cần phải quay trở lại một phiên bản, nó là chính xác giống như một bạn đã thử nghiệm trong phát triển. Điều đó cũng giải quyết vấn đề của bạn về các xung đột hợp nhất đã giải quyết trước đó.

Nếu bạn không quan tâm đến việc lưu giữ lịch sử, bạn có thể tạo một nhánh mới ngoài tổng thể, kiểm tra nó, sau đó thực hiện git read-tree -u -m devcập nhật cây làm việc của bạn để khớp với devnhánh đó. Sau đó, bạn có thể cam kết mọi thứ thành một cam kết lớn và hợp nhất nó thành tổng thể như bình thường.


1
Những gì bạn đã làm hiệu quả ở đây là hợp nhất. Chi nhánh mới là không cần thiết.
Isak gilbert

1
@isakgilbert Nó chỉ giống nhau nếu bạn hợp nhất với --squash. Một hợp nhất thông thường sẽ thêm N hoặc N + 1 cam kết thành chủ nếu có N cam kết trên nhánh. Đề xuất ở trên, hoặc merge --squashsẽ luôn chỉ thêm một cam kết duy nhất vào tổng thể.
peterflynn

3
@ytpete, có chính xác. Tôi cảm thấy ở trên chỉ là một cách vòng vo để thực hiện hợp nhất --squash từ dev sang master. "Tạo một nhánh mới" chỉ là trỏ vào cùng một nơi như chính. "Cam kết mọi thứ vào một cam kết lớn" là chỉ làm bí.
isak gilbert

3
các cam kết hợp nhất bị nhiễu khi cố gắng xem toàn bộ các thay đổi trên một nhánh duy nhất. Thật khó để giải nén sự khác biệt và xem xét nó khi một lịch sử sạch sẽ khiến nó trở nên đơn giản.
Ajax

2
Tôi không thể không đồng ý hơn với một lịch sử "sạch sẽ" được đánh giá quá cao. Nó không được đánh giá quá cao, nó tiết kiệm thời gian và làm cho mọi thứ ít rắc rối hơn.
basickarl

122

git merge --squashbây giờ là cách ưa thích của tôi để phục hồi sau một lượng lớn công việc và nhiều hợp nhất ( xem câu trả lời này ). Nếu nhánh bạn đang làm việc được gọi my-branchvà bạn muốn căn cứ lại từ masterđó chỉ cần làm như sau:

git checkout my-branch
git branch -m my-branch-old
git checkout master
git checkout -b my-branch
git merge --squash my-branch-old
git commit

12

Hai nhận xét:

  • bạn có thể căn cứ lại công việc của riêng bạn (chưa được đẩy) bao nhiêu lần tùy thích trên đầu các cam kết mới được tìm nạp.
  • Bạn có thể tránh xung đột hợp nhất (trong quá trình rebase) nếu bạn đã kích hoạtgit rerere , điều này được thực hiện cho loại tình huống này.
    http://git-scm.com/images/rerere2.png Xem thêm tại git rerere.

@lulian: trong trường hợp đó, nếu bạn phải căn cứ lại công việc của mình, tôi nghĩ bạn sẽ phải thực hiện lại các giải pháp xung đột hợp nhất đó.
VonC

@krlmlr Cảm ơn bạn. Tôi đã khôi phục liên kết, thêm hình minh họa và tham chiếu đến trang người của lệnh đó.
VonC

8

Bạn có thể thực hiện tất cả các thay đổi trong nhánh của mình và đưa chúng vào một cam kết mới mastervới những điều sau:

git diff master > my_branch.patch
git checkout master
patch -p1 < my_branch.patch

Sau đó phân chia các tệp của bạn và cam kết.


1

Về việc phát lại các xung đột hợp nhất, bạn có thể sử dụng git rerere để duy trì cơ sở dữ liệu về cách các xung đột hợp nhất đã được giải quyết, để việc thực hiện rebase dẫn đến các xung đột tương tự sẽ tự động thực hiện các phần tốn công sức cho bạn.

https://hackernoon.com/fix-conflicts-only-once-with-git-rerere-7d116b2cec67

git config --global rerere.enabled true

Một điều cần lưu ý là nếu bạn giải quyết sai điều gì đó, nó sẽ tự động được xử lý cho bạn vào lần sau và bạn có thể không thực sự nhận ra điều đó.

Tài liệu chính thức hơn tại đây: https://git-scm.com/docs/git-rerere

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.