đẩy - cưỡng bức với cho thuê theo mặc định


130

Tôi chỉ học về git push --force-with-lease. Nó thật tuyệt vời. Nhưng, tất nhiên, tôi không sử dụng vũ lực thường xuyên, và vì vậy tôi lo lắng rằng tôi có thể quên đi tính năng tiện lợi này vào lần tới khi tôi cần.

Có cách nào để cấu hình git để git push -ftự động sử dụng --force-with-leasetrừ khi tôi cố tình ghi đè lên nó --no-force-with-leasekhông?

(Tôi không thể tưởng tượng được bao giờ muốn sử dụng vũ lực mà không cần thuê!)

Câu trả lời:


141

AFAIK không có cấu hình có sẵn để bảo git luôn luôn sử dụng force-with-leasethay vì force. Đây dường như là một ví dụ tốt cho một yêu cầu tính năng; nếu bạn không gặp vấn đề gì khi đi sâu vào cơ sở mã git, bạn có thể tự thực hiện và gửi nó để xem xét.

EDIT Như hiện tại, điều này vẫn đúng trong tháng 4 năm 2019.

Cho đến lúc đó, lựa chọn duy nhất tôi thấy là, như thường xuyên, để tạo ra một aliasmục đích phục vụ mục đích này.

Tạo một bí danh

Để tạo một bí danh người ta sẽ sử dụng git config --global alias.<alias-name> <command>, trong trường hợp của chúng tôi, tôi sẽ đề xuất một cái gì đó tương tự như thế này.

git config --global alias.pushf "push --force-with-lease"

Điều này sẽ tạo ra một mục trong .gitconfigtệp toàn cầu của bạn (mà bạn thường có thể tìm thấy trong thư mục nhà của bạn ). Sau này, bạn có thể chỉ cần sử dụng git pushfđể buộc thuê .

Lấy tay bẩn

Nếu bạn muốn tự thực hiện tính năng này nhưng không chắc bắt đầu từ đâu, trước tiên bạn nên xem thư mục tài liệu trong kho git . Tại đây bạn có thể tìm thấy các hướng dẫn mã hóa và thông tin về cách gửi các bản vá .

Bạn có thể tìm thấy tất cả các liên kết này và nhiều hơn nữa trên trang cộng đồng chính thức .


25
Một lưu ý về điều này không phải là một tính năng: đối số phổ biến chống lại việc viết lại các lệnh tiêu chuẩn ("lực đẩy") là bạn đã quen với chúng, quên nguồn gốc của chúng và một ngày nào đó vô tình sử dụng chúng theo cách đó trên một hệ thống mới. Giống như răng cưa rmđể rm -itrong .bashrc của bạn; một ngày nào đó bạn sẽ quên và xóa một tập tin quan trọng trên máy chủ. Đi với bí danh của riêng bạn không có vấn đề đó :)
hraban

2
Giai thoại cá nhân / lời cảnh báo: Tôi đã thử đặt bí danh cho nó pushfnhưng luôn kiểm tra kỹ rằng tôi không làm gì push -f, do nó trông giống với bí danh. Một số thành viên trong nhóm đã sử dụng push -fdù sao đi nữa, nghĩ rằng bí danh chỉ là một tốc ký thẩm mỹ cho nó. Cuối cùng, chúng tôi đã đặt bí danh cho hình thức an toàn hơn để pushflthay thế và ngừng lo lắng về nó.
kelvin

31

Tôi lo lắng rằng tôi có thể quên tính năng tiện lợi này vào lần tới khi tôi cần nó.

Git 2.13 (Q2 2017) giải thích lý do tại sao không có "sự bảo vệ" nào đối với tùy chọn đẩy này bị lãng quên, bởi vì ngay cả khi bạn không quên nó ở git pushcấp độ, nó vẫn có thể bị bỏ qua.

Xem cam kết f17d642 (19 tháng 4 năm 2017) của Ævar Arnfjorð Bjarmason ( avar) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 46bdfa3 , ngày 26 tháng 4 năm 2017)

push: tài liệu & kiểm tra --force-with-leasevới nhiều điều khiển từ xa

Tài liệu & kiểm tra cho các trường hợp có hai điều khiển từ xa trỏ đến cùng một URL và tìm nạp nền & sau đó git push --force-with-leasekhông nên ghi lại các tham chiếu chưa cập nhật mà chúng tôi chưa tìm nạp.

Một số trình soạn thảo như VSC của Microsoft có tính năng tự động tìm nạp trong nền, điều này bỏ qua các biện pháp bảo vệ được cung cấp bởi --force-with-lease&--force-with-lease=<refname> , như đã lưu ý trong tài liệu được thêm vào đây.

Vì vậy, các tài liệu chogit push bây giờ bao gồm:

lưu ý chung về an toàn: cung cấp tùy chọn này mà không có giá trị mong đợi, nghĩa là --force-with-leasehoặc --force-with-lease=<refname> tương tác rất xấu với bất cứ thứ gì ngầm chạy git fetchtrên điều khiển từ xa để được đẩy xuống nền, ví dụ như git fetch origin trên kho lưu trữ của bạn trong một cronjob.

Sự bảo vệ mà nó mang lại --forcelà đảm bảo rằng những thay đổi tiếp theo mà công việc của bạn không dựa trên không bị ghi đè, nhưng điều này bị đánh bại một cách tầm thường nếu một số quy trình nền đang cập nhật các ref trong nền. Chúng tôi không có bất cứ điều gì ngoại trừ thông tin theo dõi từ xa sẽ xuất hiện dưới dạng heuristic cho các ref mà bạn dự kiến ​​sẽ thấy và sẵn sàng ghi đè.

Nếu trình soạn thảo của bạn hoặc một số hệ thống khác đang chạy git fetchtrong nền cho bạn một cách để giảm thiểu điều này là chỉ cần thiết lập một điều khiển từ xa khác:

git remote add origin-push $(git config remote.origin.url)
git fetch origin-push

Bây giờ khi quá trình nền chạy git fetch origincác tham chiếu trên origin-pushsẽ không được cập nhật và do đó các lệnh như:

git push --force-with-lease origin-push

Sẽ thất bại trừ khi bạn tự chạy git fetch origin-push.
Phương pháp này tất nhiên bị đánh bại hoàn toàn bởi một cái gì đó chạy git fetch --all, trong trường hợp đó bạn cần phải vô hiệu hóa nó hoặc làm một cái gì đó tẻ nhạt hơn như:

git fetch              # update 'master' from remote
git tag base master    # mark our base point
git rebase -i master   # rewrite some commits
git push --force-with-lease=master:base master:master

Tức là tạo một basethẻ cho các phiên bản của mã ngược dòng mà bạn đã thấy và sẵn sàng ghi đè, sau đó viết lại lịch sử và cuối cùng buộc thay đổi đẩy sang masternếu phiên bản từ xa vẫn còn base, bất kể nội bộ của bạn remotes/origin/masterđã được cập nhật trong lý lịch.


30

Giải pháp của tôi là tạo ra một kịch bản lệnh bao bọc và sử dụng bí danh để tôi luôn sử dụng nó thay cho thực tế git.

Bất cứ khi nào tôi cố gắng git push -f, tôi thấy như sau:

⚡ git push -f
use this instead so you don't cause race conditions in the 
repo: git push --force-with-lease

Một số ưu điểm của kịch bản này là:

  • nó huấn luyện tôi sử dụng theo thói quen --force-with-lease, vì vậy tôi không bị cằn nhằn khi tôi hiểu sai
  • nếu, vì một số lý do, chúng tôi thực sự cần phải đẩy, git push --forcesẽ làm việc.

Cách thực hiện:

  1. tạo một tập lệnh tùy chỉnh sẽ đi qua bất kỳ thông số nào để git, ngoại trừ -f
  2. bí danh kịch bản để chúng tôi sử dụng nó thay vì git

Các hướng dẫn này giả định Linux hoặc Mac, chạy bash. Tôi đã không thử điều này với zsh hoặc Windows, nhưng tôi cho rằng nó cũng sẽ hoạt động ở đó.

~/.bash_profile:

alias git=~/.git_wrapper.sh

~./git_wrapper.sh:

#!/bin/bash
for arg in "$@"; do
    if [ "$arg" = "push" ]; then
        ispush=1
    elif [ "$ispush" = 1 -a "$arg" = '-f' ]; then
        echo "use this instead so you don't cause race conflicts in the repo: git push --force-with-lease"
        exit 1
    fi
done

git "$@"

Với những thay đổi đó, hãy khởi động lại thiết bị đầu cuối của bạn và gitbây giờ sẽ trở nên khó chịu khi bạn cố gắng đẩy.


17
Điều đó có vẻ thuận tiện. +1. Có thể thay thế "hey idiot" bằng "hey, bạn hiền lành nhưng tâm hồn đơn giản" hoặc một số người như thế;)
VonC

5

Đối với những người sử dụng OMYZSH, bạn chỉ cần sử dụng ggfl.


3

Tôi muốn được nhắc nhở rằng tôi không nên sử dụng -f, nhưng tôi không muốn bị lừa tin vào điều đó -fcó nghĩa --force-with-lease. Vì vậy, đây là mất của tôi:

git() {
  if [[ $@ == 'push -f'* ]]; then
    echo Hey stupid, use --force-with-lease instead
  else
    command git "$@"
  fi
}

Thêm vào của bạn .bash_profile, .bashrchoặc .zshrc.


1

Bạn có thể tạo một hàm bash thay thế gitvà sử dụng --force-with-leasethay vì--force

# replaces `git push --force` with `git push --force-with-lease`
git() {
  if [[ $@ == 'push -f'* || $@ == 'push --force'* ]]; then
    command git push --force-with-lease
  else
    command git "$@"
  fi
}

hoặc, trong một dòng:

git() { if [[ $@ == 'push -f'* || $@ == 'push --force'* ]]; then command git push --force-with-lease; else command git "$@"; fi; }

Chỉ cần thêm nó vào ~/.bashrchoặc của bạn ~/.zshrc.

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.