Nếu bạn đẩy một cam kết máy chủ, và sau đó viết lại rằng cam kết tại địa phương (với git reset
, git rebase
, git filter-branch
, hoặc bất kỳ thao tác lịch sử khác), và sau đó đẩy mà viết lại cam kết trở lại lên đến máy chủ, bạn sẽ vít lên bất kỳ ai khác đã kéo. Đây là một ví dụ; nói rằng bạn đã cam kết A và đẩy nó lên máy chủ.
- * - * - A <- chủ
- * - * - A <- origin / master
Bây giờ bạn quyết định viết lại A, theo cách bạn đã đề cập, đặt lại và cam kết lại. Lưu ý rằng điều này để lại một cam kết lơ lửng, A, cuối cùng sẽ được thu gom rác vì không thể truy cập được.
- * - * - A
\
A '<- chủ
- * - * - A <- origin / master
Nếu ai đó khác, giả sử Fred, kéo xuống master
từ máy chủ trong khi bạn đang làm việc này, họ sẽ có một tham chiếu đến A, mà họ có thể bắt đầu hoạt động từ đó:
- * - * - A '<- chủ
- * - * - A <- origin / master
- * - * - AB <- fred / master
Bây giờ nếu bạn có thể đẩy A 'của mình đến điểm gốc / cái, điều này sẽ tạo ra một chuyển tiếp không nhanh, nó sẽ không có A trong lịch sử của nó. Vì vậy, nếu Fred cố gắng kéo lại, anh ấy sẽ đột nhiên phải hợp nhất và sẽ giới thiệu lại cam kết A:
- * - * - A '<- chủ
- * - * - A <- origin / master
- * - * - AB- \
\ * <- fred / master
A '- /
Nếu Fred tình cờ nhận thấy điều này, thì anh ta có thể thực hiện rebase, điều này sẽ ngăn cam kết A xuất hiện trở lại. Nhưng anh ấy sẽ phải nhận thấy điều này, và nhớ làm điều này; và nếu bạn có nhiều hơn một người đã kéo A xuống, tất cả họ sẽ phải căn cứ lại để tránh nhận thêm A cam kết trong cây.
Vì vậy, nói chung không phải là một ý kiến hay nếu thay đổi lịch sử trên repo mà người khác lấy từ đó. Tuy nhiên, nếu bạn tình cờ biết rằng không có ai khác đang lấy từ repo đó (ví dụ: đó là repo riêng tư của bạn hoặc bạn chỉ có một nhà phát triển khác làm việc trong dự án mà bạn có thể phối hợp dễ dàng), thì bạn có thể buộc cập nhật bằng cách chạy:
git push -f
hoặc là
git push origin +master
Cả hai điều này sẽ bỏ qua việc kiểm tra một lần đẩy không nhanh và cập nhật những gì trên máy chủ lên bản sửa đổi A 'mới của bạn, bỏ qua bản sửa đổi A để cuối cùng nó sẽ được thu gom.
Có thể lực đẩy hoàn toàn bị vô hiệu hóa với receive.denyNonFastForwards
tùy chọn cấu hình. Tùy chọn này được bật theo mặc định trên các kho được chia sẻ. Trong trường hợp đó, nếu bạn thực sự, thực sự muốn thúc đẩy, tùy chọn tốt nhất là xóa nhánh và tạo lại nó, với git push origin :master; git push origin master:master
. Tuy nhiên, denyNonFastForwards
tùy chọn được bật vì một lý do, được mô tả ở trên; trên một kho lưu trữ được chia sẻ, điều đó có nghĩa là bây giờ tất cả những người sử dụng nó cần đảm bảo rằng họ căn cứ vào lịch sử mới.
Trên một kho lưu trữ được chia sẻ, tốt hơn là chỉ cần đẩy các cam kết mới lên trên để khắc phục bất kỳ sự cố nào bạn gặp phải; bạn có thể sử dụng git revert
để tạo các cam kết sẽ hoàn tác các thay đổi của các cam kết trước đó.