Bằng cách nào đó chủ của tôi và chi nhánh gốc / chủ của tôi đã chuyển hướng.
Tôi thực sự không muốn họ phân kỳ.
Làm cách nào tôi có thể xem những khác biệt này và 'hợp nhất' chúng?
Bằng cách nào đó chủ của tôi và chi nhánh gốc / chủ của tôi đã chuyển hướng.
Tôi thực sự không muốn họ phân kỳ.
Làm cách nào tôi có thể xem những khác biệt này và 'hợp nhất' chúng?
Câu trả lời:
Bạn có thể xem lại sự khác biệt bằng:
git log HEAD..origin/master
trước khi kéo nó (tìm nạp + hợp nhất) (xem thêm "Làm thế nào để bạn có được git để luôn kéo từ một nhánh cụ thể?" )
Khi bạn có một tin nhắn như:
"Chi nhánh của bạn và 'origin / master' đã phân kỳ, # và có 1 và 1 cam kết khác nhau tương ứng."
, kiểm tra nếu bạn cần cập nhậtorigin
. Nếu origin
được cập nhật, thì một số cam kết đã được đẩy sang origin
từ một repo khác trong khi bạn thực hiện các cam kết của riêng mình tại địa phương.
... o ---- o ---- A ---- B origin/master (upstream work)
\
C master (your work)
Bạn dựa trên cam kết C trên cam kết A vì đó là công việc mới nhất mà bạn đã tìm nạp từ thượng nguồn tại thời điểm đó.
Tuy nhiên, trước khi bạn cố gắng đẩy về nguồn gốc, một người khác đã đẩy cam kết B.
Lịch sử phát triển đã chuyển hướng thành các đường dẫn riêng biệt.
Sau đó bạn có thể hợp nhất hoặc rebase. Xem Pro Git: Git Branching - Rebasing để biết chi tiết.
Hợp nhất
Sử dụng lệnh git merge:
$ git merge origin/master
Điều này nói với Git để tích hợp các thay đổi từ origin/master
vào công việc của bạn và tạo một cam kết hợp nhất.
Biểu đồ của lịch sử bây giờ trông như thế này:
... o ---- o ---- A ---- B origin/master (upstream work)
\ \
C ---- M master (your work)
Hợp nhất mới, cam kết M, có hai cha mẹ, mỗi cha mẹ đại diện cho một con đường phát triển dẫn đến nội dung được lưu trữ trong cam kết đó.
Lưu ý rằng lịch sử đằng sau M bây giờ là phi tuyến tính.
Nổi loạn
Sử dụng lệnh git rebase:
$ git rebase origin/master
Điều này nói với Git phát lại cam kết C (công việc của bạn) như thể bạn đã dựa trên cam kết B thay vì A.
CVS và người dùng Subversion thường xuyên phản hồi các thay đổi cục bộ của họ trên đầu công việc ngược dòng khi họ cập nhật trước khi cam kết.
Git chỉ thêm phân tách rõ ràng giữa các bước cam kết và rebase.
Biểu đồ của lịch sử bây giờ trông như thế này:
... o ---- o ---- A ---- B origin/master (upstream work)
\
C' master (your work)
Cam kết C 'là một cam kết mới được tạo bởi lệnh git rebase.
Nó khác với C theo hai cách:
Lưu ý rằng lịch sử đằng sau C 'vẫn là tuyến tính.
Chúng tôi đã chọn (bây giờ) chỉ cho phép lịch sử tuyến tính trong cmake.org/cmake.git
.
Cách tiếp cận này bảo tồn quy trình làm việc dựa trên CVS được sử dụng trước đây và có thể dễ dàng chuyển đổi.
Một nỗ lực để đẩy C 'vào kho lưu trữ của chúng tôi sẽ hoạt động (giả sử bạn có quyền và không ai bị đẩy trong khi bạn đang khởi động lại).
Lệnh git pull cung cấp một cách tốc ký để tìm nạp từ nguồn gốc và khởi động lại công việc cục bộ trên nó:
$ git pull --rebase
Điều này kết hợp các bước tìm nạp và rebase ở trên thành một lệnh.
git reset --hard HEAD
sẽ chỉ xóa bất kỳ sửa đổi không cam kết được lập chỉ mục cục bộ nào và sẽ không làm gì để điều hòa sự khác biệt giữa các cam kết cục bộ và từ xa . Chỉ một sự hợp nhất hoặc một cuộc nổi loạn sẽ mang lại hai tập hợp các cam kết (một cục bộ và một từ xa) cùng nhau.
master
chỉ ra B
ví dụ của bạn.
git reset --hard origin/master
như được đề cập trong câu trả lời ngay bên dưới: stackoverflow.com/a/8476004/6309
Tôi đã có điều này và đang bối rối về những gì đã gây ra nó, ngay cả sau khi đọc các phản hồi trên. Giải pháp của tôi là làm
git reset --hard origin/master
Sau đó, nó chỉ đặt lại bản sao chính (cục bộ) của tôi (mà tôi giả sử đã được vặn lên) đến đúng điểm, như được biểu thị bằng (gốc) gốc / từ xa.
CẢNH BÁO : Bạn sẽ mất tất cả các thay đổi chưa được đẩy tới
origin/master
.
git reflog
hoặc xem chúng trong gitk --all
. Tuy nhiên, tất nhiên, thiết lập lại cứng là một điều khác hơn là một rebase.
git pull --rebase origin/master
là một lệnh duy nhất có thể giúp bạn hầu hết thời gian.
Chỉnh sửa: Kéo các xác nhận từ nguồn gốc / bản gốc và áp dụng các thay đổi của bạn theo lịch sử chi nhánh mới được kéo.
Tôi thấy mình trong tình huống này khi tôi đã cố gắng để rebase một chi nhánh đã được theo dõi một chi nhánh từ xa, và tôi đã cố gắng để rebase nó trên tổng thể. Trong trường hợp này nếu bạn cố gắng nổi loạn, rất có thể bạn sẽ thấy chi nhánh của mình bị chuyển hướng và nó có thể tạo ra một mớ hỗn độn không dành cho git nubees!
Giả sử bạn đang ở chi nhánh my_remote_tracking_branch, được phân nhánh từ chủ
$ git status
# Trên nhánh my_remote_tracking_branch
không có gì để cam kết (thư mục làm việc sạch sẽ)
Và bây giờ bạn đang cố gắng để nổi loạn từ chủ như:
git rebase chủ
DỪNG NGAY và tiết kiệm cho mình một số rắc rối! Thay vào đó, sử dụng hợp nhất như:
chủ git merge
Có, bạn sẽ kết thúc với các cam kết thêm trên chi nhánh của bạn. Nhưng trừ khi bạn sẵn sàng cho các nhánh "không phân kỳ", đây sẽ là một quy trình công việc trơn tru hơn nhiều so với việc khởi động lại. Xem blog này để được giải thích chi tiết hơn nhiều.
Mặt khác, nếu chi nhánh của bạn chỉ là một chi nhánh địa phương (tức là chưa được đẩy đến bất kỳ điều khiển từ xa nào), bạn chắc chắn nên thực hiện một rebase (và chi nhánh của bạn sẽ không phân kỳ trong trường hợp này).
Bây giờ nếu bạn đang đọc bài viết này bởi vì bạn đã là một "tách ra" kịch bản do rebase như vậy, bạn có thể trở lại các cam kết cuối cùng từ gốc (tức là trong tình trạng bỏ tách ra) bằng cách sử dụng:
thiết lập lại git - nguồn gốc gốc / my_remote_tracking_branch
rebase
nếu nhánh bạn đang nổi loạn chưa được công bố (và được người khác sử dụng). Nếu không, sử dụng merge
. Nếu bạn rebase các nhánh đã được xuất bản (và đã sử dụng), bạn phải phối hợp một âm mưu để viết lại lịch sử trên mọi nhà phát triển đã sử dụng chi nhánh của bạn.
git rebase master
...
git reset --hard origin/my_remote_tracking_branch
là những gì thực sự làm việc
Trong trường hợp của tôi, đây là những gì tôi đã làm để gây ra thông điệp chuyển hướng: Tôi đã làm git push
nhưng sau đó đã làm git commit --amend
để thêm một cái gì đó vào thông điệp cam kết. Sau đó tôi cũng đã làm một cam kết khác.
Vì vậy, trong trường hợp của tôi, điều đó chỉ có nghĩa là nguồn gốc / chủ đã hết hạn. Bởi vì tôi biết không có ai khác chạm vào nguồn gốc / chủ, cách khắc phục là không đáng kể: git push -f
( -f
có nghĩa là lực lượng)
git push -f
để ghi đè lên các thay đổi đã cam kết trước đó và được đẩy về nguồn gốc. Tôi cũng chắc chắn không ai khác chạm vào kho lưu trữ.
Trong trường hợp của tôi, tôi đã đẩy các thay đổi sang origin/master
và sau đó nhận ra rằng tôi không nên làm như vậy :-( Điều này rất phức tạp bởi thực tế là các thay đổi cục bộ nằm trong một cây con. Vì vậy, tôi đã quay lại cam kết tốt cuối cùng trước địa phương "xấu" thay đổi (sử dụng SourceTree) và sau đó tôi nhận được "thông báo phân kỳ".
Sau khi sửa lỗi cục bộ của tôi cục bộ (các chi tiết không quan trọng ở đây), tôi muốn "quay ngược thời gian" origin/master
chi nhánh từ xa để nó sẽ đồng bộ lại với cục bộ master
. Giải pháp trong trường hợp của tôi là:
git push origin master -f
Lưu ý công tắc -f
(lực). Điều này đã xóa "những thay đổi xấu" đã bị đẩy sang origin/master
nhầm lẫn và bây giờ các chi nhánh địa phương và từ xa đã đồng bộ.
Xin lưu ý rằng đây là một hoạt động có khả năng phá hủy, vì vậy chỉ thực hiện nếu bạn chắc chắn 100% rằng "di chuyển trở lại" chủ thời gian từ xa là ổn.
You are not allowed to force push code to a protected branch on this project.
. Tôi đang cố gắng đẩy đến ngã ba của tôi.
Tôi biết có rất nhiều câu trả lời ở đây, nhưng tôi nghĩ rằng nó git reset --soft HEAD~1
đáng được chú ý, bởi vì nó cho phép bạn giữ những thay đổi trong cam kết cục bộ (không bị đẩy) trong khi giải quyết trạng thái chuyển hướng. Tôi nghĩ rằng đây là một giải pháp linh hoạt hơn so với kéo rebase
, bởi vì cam kết cục bộ có thể được xem xét và thậm chí chuyển sang chi nhánh khác.
Chìa khóa đang sử dụng --soft
, thay vì khắc nghiệt --hard
. Nếu có nhiều hơn 1 cam kết, một biến thể HEAD~x
sẽ hoạt động. Vì vậy, đây là tất cả các bước giải quyết tình huống của tôi (tôi đã có 1 cam kết cục bộ và 8 cam kết trong điều khiển từ xa):
1) git reset --soft HEAD~1
để hoàn tác cam kết địa phương. Đối với các bước tiếp theo, tôi đã sử dụng giao diện trong SourceTree, nhưng tôi nghĩ các lệnh sau cũng sẽ hoạt động:
2) git stash
để stash thay đổi từ 1). Bây giờ tất cả các thay đổi đều an toàn và không còn phân kỳ nữa.
3) git pull
để có được những thay đổi từ xa.
4) git stash pop
hoặc git stash apply
để áp dụng các thay đổi được lưu trữ cuối cùng, theo sau là một cam kết mới, nếu muốn. Bước này là tùy chọn, cùng với 2) , khi muốn dọn rác các thay đổi trong cam kết cục bộ. Ngoài ra, khi muốn cam kết với một chi nhánh khác, bước này nên được thực hiện sau khi chuyển sang chi nhánh mong muốn.
pull --rebase
dù sao đi nữa, stash sẽ tự động. stackoverflow.com/a/30209750/6309
Để xem sự khác biệt:
git difftool --dir-diff master origin/master
Điều này sẽ hiển thị những thay đổi hoặc khác biệt giữa hai nhánh. Trong araxis (Yêu thích của tôi), nó hiển thị nó theo kiểu khác thư mục. Hiển thị từng tệp đã thay đổi. Sau đó tôi có thể nhấp vào một tệp để xem chi tiết về các thay đổi trong tệp.
Trong trường hợp của tôi, điều này là do không cam kết giải quyết xung đột của tôi.
Vấn đề là do chạy git pull
lệnh. Thay đổi trong nguồn gốc dẫn đến xung đột với repo địa phương của tôi, mà tôi đã giải quyết. Tuy nhiên, tôi đã không cam kết chúng. Giải pháp tại thời điểm này là cam kết các thay đổi ( git commit
tệp đã giải quyết)
Nếu bạn cũng đã sửa đổi một số tệp kể từ khi giải quyết xung đột, git status
lệnh sẽ hiển thị các sửa đổi cục bộ dưới dạng sửa đổi cục bộ không được chỉnh sửa và hợp nhất độ phân giải như sửa đổi cục bộ theo giai đoạn. Điều này có thể được giải quyết một cách chính xác bằng cách cam kết các thay đổi từ hợp nhất trước git commit
, sau đó thêm và cam kết các thay đổi chưa được xử lý như bình thường (ví dụ: bởi git commit -a
).
Tôi đã có cùng một thông báo khi tôi đang cố gắng chỉnh sửa tin nhắn cam kết cuối cùng, về cam kết đã được đẩy, bằng cách sử dụng: git commit --amend -m "New message"
Khi tôi đẩy các thay đổi bằng cách sử dụng git push --force-with-lease repo_name branch_name
không có vấn đề gì.
Gặp vấn đề này khi tôi tạo một nhánh dựa trên nhánh A bằng
git checkout -b a
và sau đó tôi thiết lập luồng lên của nhánh a thành nhánh B
git branch -u origin/B
Sau đó tôi nhận được thông báo lỗi ở trên.
Một cách để giải quyết vấn đề này cho tôi là,
git checkout -b b origin/B