Làm cách nào để buộc git pull ghi đè lên mọi thứ trên mỗi lần kéo?


203

Tôi có một kho lưu trữ trần TRUNG TÂM có ba kho lưu trữ dành cho nhà phát triển kéo và đẩy vào đó một cách bình thường.

Tôi cũng có hai kho lưu trữ khác được lấy từ repo trần TRUNG TÂM: một là máy chủ trực tiếp và một là máy chủ thử nghiệm / giai đoạn mà mỗi máy kéo từ chi nhánh tương ứng của nó.

Kịch bản là thế này: Tôi có một post-updatetập lệnh hook trên repo TRUNG TÂM tự động truy cập các bài kiểm tra và repos trực tiếp và chạy một lệnh kéo trên mỗi. Điều này cập nhật cả máy chủ thử nghiệm và máy chủ trực tiếp, tất cả tùy thuộc vào chi nhánh nào có cam kết mới. Tất cả điều này làm việc tuyệt vời.

Vấn đề là ở đây: có thể trong trường hợp khẩn cấp, các tệp có thể được cập nhật trực tiếp trên máy chủ (thông qua ftp hoặc bất cứ điều gì) và tập lệnh cập nhật sau TRUNG TÂM sẽ thất bại do xung đột hợp nhất / ghi đè sẽ xảy ra. Không có cách nào để tránh kịch bản này, và đó là điều không thể tránh khỏi.

Điều tôi muốn xảy ra là thế này: Tôi muốn kéo từ các trang web trực tiếp và thử nghiệm luôn ghi đè / hợp nhất khi kéo. Luôn luôn. Những repos này sẽ chỉ kéo vì chúng không dành cho phát triển.

Trong tất cả các nghiên cứu của tôi, tôi không thể tìm ra một giải pháp tốt để có một lực kéo luôn buộc ghi đè lên các tệp cục bộ. Đây có phải là ở tất cả có thể? Nó sẽ làm cho một kịch bản phát triển tuyệt vời nếu như vậy.


1
Mặc dù tôi đã bình chọn cho câu trả lời 'đặt lại cho câu trả lời bạn vừa tải xuống bên dưới, tôi nghĩ giải pháp cho vấn đề thực sự của bạn là không thực hiện các thay đổi ngoài băng tần. Sửa đổi, bất kể khẩn cấp như thế nào, phải luôn luôn đi qua kiểm soát phiên bản. Không ai ngoại trừ các nhà khai thác nên có quyền truy cập trực tiếp vào các trang web đang chạy (ví dụ: không phải nhà phát triển). Sử dụng kiểm soát phiên bản một cách nhất quán có nghĩa là bạn có bản ghi về thời điểm thay đổi được thực hiện và ai đã thực hiện chúng và các công cụ tốt hơn để làm việc với chúng. Tại sao lật đổ nó, không có lợi ích thực sự?
Phil Miller

1
@Nigsocrat đúng, tôi hiểu những gì bạn đang nói. Thật không may, có một số tình huống trong đó ai đó có thể tải tệp trực tiếp lên máy chủ. Trong trường hợp đó tôi sẽ cần chạy một số lệnh để đồng bộ lại các repos. Trước đây chúng tôi đã sử dụng tập lệnh FTP để di chuyển tệp từ repo sang máy chủ. Phương pháp được đề xuất ở trên chỉ đơn giản là loại bỏ bước FTP, hoạt động rất tốt trong quá khứ.
bmilesp

3
Vì vậy, đừng để mọi người truy cập trực tiếp vào máy chủ. Khóa quyền truy cập FTP và SSH hoặc nói với họ rằng họ sẽ bị sa thải vì thực hiện các thay đổi không thể đếm được. Để loại thực hành đó tiếp tục chỉ làm tổn thương bạn và nhóm của bạn về lâu dài.
Phil Miller

Câu trả lời:


510

Thực sự cách lý tưởng để làm điều này là không sử dụng pull, mà thay vào đó fetchreset:

git fetch origin master
git reset --hard FETCH_HEAD
git clean -df

(Thay đổi masterbất cứ chi nhánh nào bạn muốn theo dõi.)

pullđược thiết kế xung quanh việc hợp nhất các thay đổi với nhau theo một cách nào đó, trong khi đó resetđược thiết kế chỉ đơn giản là làm cho bản sao cục bộ của bạn khớp với một cam kết cụ thể.

Bạn có thể muốn xem xét các tùy chọn hơi khác nhau tùy cleanthuộc vào nhu cầu hệ thống của bạn.


3
@ user730569 reset --hardlà một lệnh được sử dụng để buộc trạng thái của thư mục làm việc (và nhánh hiện tại) thành trạng thái khớp với trạng thái của một cam kết cụ thể.
Amber

25
FETCH_HEADlà một tham chiếu được tự động tạo bởi fetchđể đại diện cho ref được tìm nạp. Nó không được hợp nhất, chỉ cần ghi đè lên bất cứ khi nào bạn thực hiện tìm nạp. cleanlà một lệnh loại bỏ các tệp không được theo dõi bởi git, các -dfcờ bảo nó xóa các thư mục ( -d) và thực sự loại bỏ ( -f).
Amber

4
Tại sao không có từ khóa cho việc này? Tôi cần điều này thường xuyên hơn nhiều so với kéo.
Wolfgang Fahl

14
Bạn có thể muốn sử dụng git clean -dntrước khi sử dụng git clean -dfvì vậy bạn sẽ thấy những tập tin / thư mục nào sẽ bị xóa. git clean -dfchỉ có thể được đảo ngược nếu bạn có một bản sao lưu
Ibrahim Lawal

1
@NickMiddleweek Tôi đã lo lắng git clean -dfsẽ loại bỏ các tập tin gitignored, nhưng hóa ra nó sẽ không. git clean --helpnói "Thông thường, chỉ các tệp không xác định với Git bị xóa, nhưng nếu tùy chọn -x được chỉ định, các tệp bị bỏ qua cũng bị xóa. Ví dụ, điều này có thể hữu ích để xóa tất cả các sản phẩm xây dựng."
nickang


6

Tôi không chắc làm thế nào để thực hiện nó trong một lệnh nhưng bạn có thể làm một cái gì đó như:

git reset --hard
git pull

hoặc thậm chí

git stash
git pull

Để chạy trong một lệnh : git reset --hard && git pull. Ngoài ra, nhưng không tốt hơn , git reset --hard; git pull. Sử dụng &&sẽ chỉ chạy lệnh thứ hai nếu lệnh đầu tiên thành công. ;sẽ chạy nó bất kể mã thoát của lệnh đầu tiên.
mazunki

5

Để lấy một bản sao của nhánh và buộc ghi đè lên các tệp cục bộ từ nguồn gốc, hãy sử dụng:

git reset --hard origin/current_branch

Tất cả công việc hiện tại sẽ bị mất và sau đó sẽ giống như nhánh gốc



2

Bạn có thể thay đổi móc để lau sạch mọi thứ.

# Danger! Wipes local data!

# Remove all local changes to tracked files
git reset --hard HEAD

# Remove all untracked files and directories
git clean -dfx

git pull ...

2
x làm gì vui lòng giải thích các công tắc
Steve K

2
X được cho là để loại bỏ tất cả các tập tin chưa được theo dõi, tôi nghĩ vậy. Khó có thể nói trong manpage-speak, đó là lý do tại sao chúng ta có SO.
JosephK

2
@JosephK: Điều đó không chính xác. Mục đích cơ bản của git cleanđã là "Xóa các tệp không bị theo dõi khỏi cây làm việc" (trên cùng của trang). Thông thường, điều này không bao gồm các file bị bỏ qua, nhưng -xnói git cleanđể bao gồm các file bỏ qua là tốt (trừ này không ảnh hưởng đến các file bỏ qua -etùy chọn).
Dietrich Epp

2

Nếu bạn chưa thực hiện các thay đổi cục bộ kể từ lần kéo / sao cuối cùng, bạn có thể sử dụng:

git checkout *
git pull

checkoutsẽ xóa các thay đổi cục bộ của bạn với cam kết cục bộ cuối cùng và pullsẽ xác nhận lại nó vào kho lưu trữ từ xa

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.