Tại sao tôi lại hợp nhất chi nhánh theo dõi từ xa 'nguồn gốc / phát triển' để phát triển?


125

Tôi là người duy nhất trong tổ chức của mình thực hiện các cam kết với thông báo sau:

Hợp nhất chi nhánh theo dõi từ xa 'nguồn gốc / phát triển' để phát triển

Không chắc chắn những gì tôi đang làm để gây ra cho họ, nhưng tôi muốn dừng lại.

Tôi đang ban hành lệnh nào để tạo ra cam kết này và lệnh nào tôi nên sử dụng để không tạo ra nó?


1
Câu trả lời của Richard Hansen là tốt. Nhưng tôi nghĩ nó có thể gây nhầm lẫn cho người mới bắt đầu. Giải pháp của tôi là tiếp tục thực hiện thao tác kéo - nhưng để tránh nguy hiểm, tôi sẽ thay đổi trước khi kéo. Sau đó, sau khi kéo, tôi áp dụng nó. Tôi giải quyết mâu thuẫn. Cuối cùng tôi có thể cam kết & đẩy.
Johnjohn

git pull --autostash --rebaselàm việc cho bạn @Johnjohn không?
sourcedelica

Câu trả lời:


206

git pullcó lẽ đang tạo ra các cam kết. Nếu bạn thực hiện một cam kết cục bộ và sau đó chạy git pullsau khi người khác đẩy một cam kết lên kho lưu trữ, Git tải xuống cam kết của nhà phát triển khác và sau đó hợp nhất nó vào chi nhánh địa phương của bạn.

Làm thế nào để tránh những cam kết hợp nhất này trong tương lai

Bạn có thể sử dụng git pull --rebaseđể ngăn chặn điều này xảy ra trong tương lai, nhưng việc nổi loạn có những nguy hiểm và tôi khuyên bạn nên tránh pullhoàn toàn .

Thay vào đó, tôi khuyến khích bạn làm theo mô hình sử dụng này:

# download the latest commits
git remote update -p

# update the local branch
git merge --ff-only @{u}

# if the above fails with a complaint that the local branch has
# diverged:
git rebase -p @{u}

Giải trình

  • git remote update -ptải xuống tất cả các cam kết trong kho lưu trữ từ xa và cập nhật các nhánh theo dõi từ xa (ví dụ origin/master:). Nó KHÔNG chạm vào thư mục làm việc, chỉ mục hoặc các nhánh cục bộ của bạn.

    Các -pđối số cắt tỉa xóa chi nhánh thượng nguồn. Do đó, nếu foonhánh bị xóa trong originkho lưu trữ, git remote update -psẽ tự động xóa origin/fooref của bạn .

  • git merge --ff-only @{u}nói với Git để hợp nhất nhánh ngược dòng ( @{u}đối số) vào nhánh cục bộ của bạn nhưng chỉ khi nhánh cục bộ của bạn có thể được "chuyển tiếp nhanh" đến nhánh ngược dòng (nói cách khác, nếu nó không được chuyển hướng).

  • git rebase -p @{u}di chuyển một cách hiệu quả các cam kết bạn đã thực hiện nhưng chưa được đẩy lên trên nhánh thượng nguồn, điều này giúp loại bỏ nhu cầu tạo ra các cam kết ngớ ngẩn mà bạn đang cố gắng tránh. Điều này cải thiện tính tuyến tính của lịch sử phát triển, giúp dễ dàng xem xét hơn.

    Các -ptùy chọn cho Git để giữ gìn hòa trộn. Điều này ngăn Git tuyến tính hóa các cam kết bị từ chối. Điều này rất quan trọng nếu, ví dụ, bạn đã hợp nhất một nhánh tính năng vào master. Nếu không -p, mọi cam kết trên nhánh tính năng sẽ được sao chép trên mastermột phần của quá trình tuyến tính hóa được thực hiện bởi git rebase. Điều này sẽ làm cho lịch sử phát triển khó xem xét hơn, không dễ dàng hơn.

    Coi chừng : git rebasecó thể không làm những gì bạn mong đợi, vì vậy hãy xem lại kết quả trước khi đẩy. Ví dụ:

    git log --graph --oneline --decorate --date-order --color --boundary @{u}..
    

Tôi thích cách tiếp cận này hơn git pull --rebasevì những lý do sau:

  • Nó cho phép bạn xem các cam kết ngược dòng đến trước khi sửa đổi lịch sử của bạn để kết hợp chúng.
  • Nó cho phép bạn chuyển tùy chọn -p( --preserve-merges) git rebasetrong trường hợp bạn cần khởi động lại một sự hợp nhất có chủ ý (ví dụ: hợp nhất một nhánh tính năng đã được đẩy vào master).

Tốc ký: git upthay vìgit pull

Để dễ thực hiện những điều trên, tôi khuyên bạn nên tạo một bí danh có tên up:

git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'

Bây giờ tất cả những gì bạn cần làm để đưa chi nhánh của bạn cập nhật là chạy:

git up

thay vì git pull. Nếu bạn gặp lỗi vì chi nhánh địa phương của bạn đã chuyển hướng từ nhánh ngược dòng, đó là gợi ý của bạn để phản ứng lại.

Tại sao không git pull --rebase?

Chạy git pull --rebasetương đương với chạy git fetchtheo sau git rebase. Điều này cố gắng chuyển nhanh tới các cam kết ngược dòng mới, nhưng nếu điều đó là không thể thì nó sẽ phản hồi các cam kết cục bộ của bạn lên các cam kết ngược dòng mới. Điều này thường ổn, nhưng hãy cẩn thận:

  • Rebase là một chủ đề nâng cao, và bạn nên hiểu ý nghĩa trước khi nổi loạn.
  • git pull --rebasekhông cho bạn cơ hội kiểm tra các cam kết trước khi kết hợp chúng. Tùy thuộc vào những gì thay đổi ở thượng nguồn, nó khá có thể là rebase là hoạt động-một sai lầm rebase --onto, merge, reset, hoặc push -fcó thể thích hợp hơn một đồng bằng rebase.
  • Hiện tại không thể chuyển --preserve-mergessang hoạt động rebase, do đó, bất kỳ sự hợp nhất có chủ ý nào của nhánh tính năng sẽ được tuyến tính hóa, phát lại (và do đó sao chép) tất cả các cam kết của nhánh tính năng.

"Sửa" một cam kết hợp nhất hiện có được tạo bởi git pull

Nếu bạn chưa đẩy một cam kết hợp nhất được tạo bởi git pull, bạn có thể loại bỏ cam kết hợp nhất. Giả sử bạn chưa thực hiện bất kỳ sự hợp nhất có chủ ý nào (ví dụ: hợp nhất một nhánh tính năng đã được đẩy vào nhánh hiện tại của bạn), thì những điều sau đây nên làm:

git rebase @{u}

Lệnh trên yêu cầu Git chọn tất cả các cam kết không hợp nhất có thể truy cập từ HEAD(cam kết hiện tại), trừ tất cả các cam kết có thể truy cập từ @{u}(đó là tốc ký cho "nhánh ngược dòng", nghĩa là, origin/masternếu HEADmaster), phát lại (cherry-pick ) chúng trên đỉnh của nhánh ngược dòng, và sau đó di chuyển tham chiếu nhánh hiện tại để trỏ đến kết quả của việc phát lại các xác nhận. Điều này có hiệu quả di chuyển các cam kết không hợp nhất vào cam kết ngược dòng gần đây nhất, loại bỏ việc hợp nhất được tạo bởi git pull.

Nếu bạn có một cam kết hợp nhất có chủ ý, bạn không muốn chạy git rebase @{u}vì nó sẽ phát lại mọi thứ từ nhánh khác. Đối phó với trường hợp này thực sự phức tạp hơn, đó là lý do tại sao nó tốt để sử dụng git upvà tránh git pullhoàn toàn. Có lẽ bạn sẽ phải sử dụng resetđể hoàn tác việc hợp nhất được tạo bởi pullvà sau đó thực hiện git rebase -p @{u}. Đối -psố git rebaseđã không hoạt động đáng tin cậy đối với tôi, vì vậy cuối cùng bạn có thể phải sử dụng resetđể hoàn tác hợp nhất có chủ ý, cập nhật chi nhánh địa phương của bạn @{u}và sau đó làm lại hợp nhất có chủ ý (đó là một nỗi đau nếu có nhiều hợp nhất lông xung đột).


+1 để thảo luận về --preserve-merges, ngoại trừ bạn không thực sự ghi lại rằng trong các lệnh bạn đã bảo anh ta chạy, vì vậy -1 cho điều đó.
Seth Robertson

@Seth: Cảm ơn bạn đã bình luận; Tôi cập nhật câu trả lời để giới thiệu -p. Tôi đã tránh đề xuất nó trước đây vì nó không cần thiết thường xuyên và hành vi của nó không được ghi chép lại.
Richard Hansen

3
Id sự khác biệt giữa git remote update -pgit fetch?
eckes

3
@eckes: git remote update -pcũng giống như git fetch --all -p. Tôi có thói quen sử dụng git remote update -ptrở lại khi fetchkhông có -ptùy chọn.
Richard Hansen

1
@ user1914692: Sau khi hợp nhất hoàn tất, Git sẽ cập nhật nhánh cục bộ để trỏ đến cam kết hợp nhất mới được tạo, không phải cho cùng một cam kết như nhánh từ xa. Cam kết hợp nhất mới này là vấn đề, đặc biệt là khi bị đẩy.
Richard Hansen

18
git fetch
git rebase origin/master

Nên làm vậy. Hoặc nếu bạn muốn tiếp tục sử dụng kéo

git pull --rebase

Bạn cũng có thể thiết lập nhánh đó trong cấu hình của mình để tự động khởi động lại hoặc tự động thiết lập như thế cho bất kỳ nhánh theo dõi nào khác trong tương lai mà bạn thực hiện. Sau đó, bạn có thể quay lại chỉ sử dụng

git pull

Thông tin thêm về điều này trong phần "kéo bằng rebase thay vì hợp nhất" của trang này:

http://mislav.uniqpath.com/2010/07/git-tips/

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.