Lực lượng git đẩy git ấn để ghi đè lên các tập tin từ xa


767

Tôi muốn đẩy các tệp cục bộ của mình và đặt chúng trên một repo từ xa mà không phải xử lý các xung đột hợp nhất. Tôi chỉ muốn phiên bản địa phương của tôi được ưu tiên hơn từ xa.

Làm thế nào tôi có thể làm điều này với Git?


106
Không git push origin --forcelàm việc cho bạn?


Không rõ nếu bạn chỉ muốn ghi đè các tệp .git hoặc bản sao làm việc được liên kết. Nếu đó là kho git, git đẩy là câu trả lời. Nếu bạn muốn cập nhật bản sao làm việc từ xa, bạn phải sử dụng móc nhận sau
Pierre-Olivier Vares

@Mike hoạt động với tôi vì một số lý do ... tự hỏi chuyện gì đã xảy ra với OP

Một nguyên nhân có thể, lực đẩy không hoạt động là, nó có thể đã bị vô hiệu hóa rõ ràng trên repo từ xa (để đảm bảo không có gì bị mất do những người đóng góp ngu ngốc và / hoặc ác tính): sử dụng config receive.denyNonFastforwardsđể tìm hiểu.
Frank Nocke 11/03/2017

Câu trả lời:


1087

Bạn sẽ có thể buộc sửa đổi cục bộ của mình vào repo từ xa bằng cách sử dụng

git push -f <remote> <branch>

(ví dụ git push -f origin master). Rời đi <remote><branch>sẽ buộc đẩy tất cả các chi nhánh địa phương đã thiết lập --set-upstream.

Chỉ cần cảnh báo, nếu những người khác đang chia sẻ kho lưu trữ này, lịch sử sửa đổi của họ sẽ xung đột với kho mới. Và nếu họ có bất kỳ cam kết địa phương nào sau thời điểm thay đổi, họ sẽ trở nên không hợp lệ.

Cập nhật : Nghĩ rằng tôi sẽ thêm một ghi chú bên. Nếu bạn đang tạo các thay đổi mà người khác sẽ xem xét, thì sẽ không có gì lạ khi tạo một nhánh với những thay đổi đó và khởi động lại định kỳ để giữ cho chúng cập nhật với nhánh phát triển chính. Chỉ cần cho các nhà phát triển khác biết điều này sẽ xảy ra theo định kỳ để họ sẽ biết những gì sẽ xảy ra.

Cập nhật 2 : Vì số lượng người xem ngày càng tăng, tôi muốn thêm một số thông tin bổ sung về những việc cần làm khi bạn upstreamgặp phải một lực đẩy.

Giả sử tôi đã nhân bản repo của bạn và đã thêm một vài cam kết như vậy:

            D ---- chủ đề
           /
A ---- B ---- C phát triển

Nhưng sau đó developmentchi nhánh bị tấn công bằng a rebase, điều này sẽ khiến tôi nhận được một lỗi như vậy khi tôi chạy git pull:

Giải nén các đối tượng: 100% (3/3), xong.
Từ <repo-location>
 * phát triển chi nhánh -> FETCH_HEAD
Tự động hợp nhất <files>
CONFLICT (nội dung): Hợp nhất xung đột ở <vị trí>
Tự động hợp nhất thất bại; khắc phục xung đột và sau đó cam kết kết quả.

Ở đây tôi có thể khắc phục các xung đột và commit, nhưng điều đó sẽ để lại cho tôi một lịch sử cam kết thực sự xấu xí:

       C ---- D ---- E ---- Chủ đề F
      / /
A ---- B -------------- C 'phát triển

Nó có thể trông hấp dẫn khi sử dụng git pull --forcenhưng hãy cẩn thận vì điều đó sẽ khiến bạn bị mắc kẹt:

            D ---- chủ đề

A ---- B ---- C 'phát triển

Vì vậy, có lẽ lựa chọn tốt nhất là làm a git pull --rebase. Điều này sẽ yêu cầu tôi giải quyết mọi xung đột như trước đây, nhưng với mỗi bước thay vì cam kết tôi sẽ sử dụng git rebase --continue. Cuối cùng, lịch sử cam kết sẽ tốt hơn nhiều:

            Chủ đề D '--- E'
           /
A ---- B ---- C 'phát triển

Cập nhật 3: Bạn cũng có thể sử dụng --force-with-leasetùy chọn này như một lực đẩy "an toàn hơn", như được đề cập bởi Cupcake trong câu trả lời của anh ấy :

Đẩy lực bằng "cho thuê" cho phép lực đẩy không thành công nếu có các cam kết mới trên điều khiển từ xa mà bạn không mong đợi (về mặt kỹ thuật, nếu bạn chưa đưa chúng vào nhánh theo dõi từ xa của bạn), rất hữu ích nếu bạn không muốn vô tình ghi đè lên các cam kết của người khác mà bạn thậm chí chưa biết và bạn chỉ muốn ghi đè lên chính mình:

git push <remote> <branch> --force-with-lease

Bạn có thể tìm hiểu thêm chi tiết về cách sử dụng --force-with-leasebằng cách đọc bất kỳ nội dung nào sau đây:


5
Vì đây là câu trả lời được chọn, tôi sẽ bình luận ở đây. Sử dụng vũ lực không phải là vấn đề khi làm việc một mình. Ví dụ: máy chủ đám mây của tôi bắt đầu bằng git của chính nó. Nếu tôi làm việc tại địa phương và xây dựng một dự án và tôi muốn đưa nó lên máy chủ đám mây của mình (OpenShift), tôi có hai dự án git riêng biệt. Địa phương của tôi và một OpenShift của tôi. Tôi nhận được địa phương của mình như tôi muốn, nhưng bây giờ muốn xem trước nó trên OpenShift của tôi. Sau đó, bạn đẩy sang OpenShift lần đầu tiên, sử dụng -fcờ. Về cơ bản đưa git cục bộ của bạn lên OpenShift.
lội vào

128

Bạn muốn đẩy

Những gì bạn về cơ bản muốn làm là buộc đẩy chi nhánh địa phương của bạn, để ghi đè lên điều khiển từ xa.

Nếu bạn muốn giải thích chi tiết hơn về từng lệnh sau, hãy xem phần chi tiết của tôi bên dưới. Về cơ bản, bạn có 4 tùy chọn khác nhau để đẩy lực bằng Git:

git push <remote> <branch> -f
git push origin master -f # Example

git push <remote> -f
git push origin -f # Example

git push -f

git push <remote> <branch> --force-with-lease

Nếu bạn muốn giải thích chi tiết hơn về từng lệnh, hãy xem phần câu trả lời dài của tôi bên dưới.

Cảnh báo: lực đẩy sẽ ghi đè lên nhánh từ xa với trạng thái của nhánh mà bạn đang đẩy. Hãy chắc chắn rằng đây là những gì bạn thực sự muốn làm trước khi sử dụng nó, nếu không bạn có thể ghi đè lên các cam kết mà bạn thực sự muốn giữ.

Lực đẩy chi tiết

Chỉ định điều khiển từ xa và chi nhánh

Bạn hoàn toàn có thể chỉ định các chi nhánh cụ thể và một điều khiển từ xa. Các -flá cờ là phiên bản ngắn--force

git push <remote> <branch> --force
git push <remote> <branch> -f

Bỏ chi nhánh

Khi nhánh để đẩy nhánh bị bỏ qua, Git sẽ tìm ra nó dựa trên cài đặt cấu hình của bạn. Trong các phiên bản Git sau 2.0, một repo mới sẽ có các cài đặt mặc định để đẩy chi nhánh hiện đang thanh toán:

git push <remote> --force

trong khi trước 2.0, các repos mới sẽ có cài đặt mặc định để đẩy nhiều nhánh cục bộ. Các cài đặt trong câu hỏi là remote.<remote>.pushpush.defaultcài đặt (xem bên dưới).

Bỏ điều khiển từ xa và chi nhánh

Khi cả điều khiển từ xa và nhánh bị bỏ qua, hành vi của chỉ git push --forceđược xác định bởi push.defaultcài đặt cấu hình Git của bạn :

git push --force
  • Kể từ Git 2.0, cài đặt mặc định, simplevề cơ bản sẽ chỉ đẩy chi nhánh hiện tại của bạn đến bộ phận từ xa ngược dòng. Điều khiển từ xa được xác định bởi branch.<remote>.remotecài đặt của chi nhánh và mặc định là repo gốc.

  • Trước Git phiên bản 2.0, cài đặt mặc định matching, về cơ bản chỉ cần đẩy tất cả các nhánh cục bộ của bạn sang các nhánh có cùng tên trên điều khiển từ xa (mặc định là gốc).

Bạn có thể đọc thêm push.defaultcài đặt bằng cách đọc git help confighoặc phiên bản trực tuyến của Trang hướng dẫn git-config (1) .

Lực đẩy an toàn hơn với --force-with-lease

Đẩy lực bằng "cho thuê" cho phép lực đẩy không thành công nếu có các cam kết mới trên điều khiển từ xa mà bạn không mong đợi (về mặt kỹ thuật, nếu bạn chưa đưa chúng vào nhánh theo dõi từ xa của bạn), rất hữu ích nếu bạn không muốn vô tình ghi đè lên các cam kết của người khác mà bạn thậm chí chưa biết và bạn chỉ muốn ghi đè lên chính mình:

git push <remote> <branch> --force-with-lease

Bạn có thể tìm hiểu thêm chi tiết về cách sử dụng --force-with-leasebằng cách đọc bất kỳ nội dung nào sau đây:


Bạn đúng, nhưng điều này thực sự chỉ nên được sử dụng trong các tình huống đặc biệt .
Scott Berrevoets

1
@ScottBerrevoets " Tôi thích là đẩy những gì tôi có và để nó ghi đè từ xa thay vì tích hợp. " Tôi đã đưa cho OP chính xác những gì anh ấy yêu cầu.

Tôi biết, nhưng OP có thể không nhận thức được hậu quả của việc này. Về mặt kỹ thuật, bạn đã trả lời câu hỏi, nhưng tôi nghĩ rằng một cảnh báo không làm điều này không đúng chỗ.
Scott Berrevoets

1
@ScottBerrevoets Tôi đang cố gắng để người điều hành hợp nhất câu trả lời của tôi vào kinh điển, bởi vì tôi đề cập đến --force-with-leasetùy chọn mới;)

1
FYI: được hợp nhất từ stackoverflow.com/questions/24768330/
Shog9

32

Một lựa chọn khác (để tránh bất kỳ sự thúc ép nào có thể gây rắc rối cho những người đóng góp khác) là:

  • đặt các cam kết mới của bạn trong một chi nhánh chuyên dụng
  • đặt lại mastervàoorigin/master
  • hợp nhất nhánh chuyên dụng của bạn với master, luôn giữ các cam kết từ nhánh dành riêng (nghĩa là tạo các bản sửa đổi mới trên đầu trang mastersẽ phản chiếu nhánh chuyên dụng của bạn).
    Xem " lệnh git để tạo một nhánh giống như một nhánh khác " để biết các chiến lược mô phỏng a git merge --strategy=theirs.

Bằng cách đó, bạn có thể đẩy chủ đến điều khiển từ xa mà không phải ép buộc bất cứ điều gì.


Làm thế nào để kết quả khác với "lực đẩy"?
alexkovelsky

6
@alexkovelsky Bất kỳ sự thúc ép bắt buộc nào cũng sẽ viết lại lịch sử, buộc những người dùng khác của repo phải thiết lập lại repo cục bộ của riêng họ để phù hợp với các cam kết vừa được đẩy. Cách tiếp cận này chỉ tạo ra các cam kết mới và không yêu cầu đẩy.
VonC

1
Tôi đề nghị bạn nên thêm một tiêu đề vào câu trả lời của mình: "Bạn không muốn ép buộc" :)
alexkovelsky

@alexkovelsky Điểm tốt. Tôi đã chỉnh sửa câu trả lời cho phù hợp.
VonC

4

git push -f có một chút phá hoại vì nó đặt lại bất kỳ thay đổi từ xa nào đã được thực hiện bởi bất kỳ ai khác trong nhóm. Tùy chọn an toàn hơn là {git push --force-with-cho thuê}.

Những gì {--force-with-cho thuê} làm là từ chối cập nhật một chi nhánh trừ khi đó là trạng thái mà chúng ta mong đợi; tức là không ai cập nhật chi nhánh ngược dòng. Trong thực tế, điều này hoạt động bằng cách kiểm tra xem ref thượng nguồn có phải là những gì chúng ta mong đợi không, bởi vì ref là băm, và ngầm mã hóa chuỗi cha mẹ thành giá trị của chúng. Bạn có thể cho {--force-with-thuê} chính xác những gì cần kiểm tra, nhưng theo mặc định sẽ kiểm tra ref từ xa hiện tại. Điều này có nghĩa là trong thực tế là khi Alice cập nhật chi nhánh của mình và đẩy nó lên kho lưu trữ từ xa, phần đầu trỏ của chi nhánh sẽ được cập nhật. Bây giờ, trừ khi Bob thực hiện thao tác kéo từ xa, tham chiếu cục bộ của anh ta đến điều khiển từ xa sẽ hết hạn. Khi anh ta đi đẩy bằng cách sử dụng {--force-with-cho thuê}, git sẽ kiểm tra giới thiệu cục bộ với điều khiển từ xa mới và từ chối buộc đẩy. {--force-with-cho thuê} chỉ cho phép bạn đẩy mạnh nếu không có ai khác đẩy các thay đổi lên đến điều khiển từ xa trong thời gian tạm thời. Đó là {--force} với dây an toàn trên.



0

Các bước đơn giản bằng cách sử dụng tortoisegit

GIT đưa ra các tệp cục bộ cam kết và đẩy vào kho git.

Các bước:

1) thay đổi stash tên stash

2) kéo

3) stash pop

4) cam kết 1 hoặc nhiều tệp và đưa ra các thay đổi mô tả tác giả và ngày

5) đẩy

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.