ผลักดัน - บังคับกับสัญญาเช่าโดยค่าเริ่มต้น


130

ฉันเพิ่งเรียนรู้เกี่ยวกับgit push --force-with-lease. มันยอดเยี่ยมมาก แต่แน่นอนว่าฉันไม่ได้ใช้กำลังบ่อยขนาดนั้นฉันจึงกังวลว่าจะลืมคุณสมบัติที่ดีนี้ในครั้งต่อไปที่ฉันต้องการ

มีวิธีกำหนดค่าคอมไพล์ที่git push -fจะใช้โดยอัตโนมัติ--force-with-leaseเว้นแต่ว่าฉันตั้งใจจะแทนที่ด้วย--no-force-with-leaseหรือไม่?

(นึกไม่ถึงว่าอยากจะใช้กำลังโดยไม่มีสัญญาเช่า!)

คำตอบ:


142

AFAIK ไม่มีการกำหนดค่าที่สามารถบอกให้ git ใช้force-with-leaseแทนforce. ดูเหมือนว่าจะเป็นตัวอย่างที่ดีสำหรับคำขอคุณลักษณะ หากคุณไม่มีปัญหาในการดำน้ำในฐานรหัสคอมไพล์คุณสามารถใช้งานได้ด้วยตัวเองและส่งเพื่อตรวจสอบ

แก้ไขตามที่กล่าวมานี้ยังคงเป็นจริงในเดือนเมษายน 2019

ก่อนหน้านี้ทางเลือกเดียวที่ฉันเห็นคือบ่อยครั้งเพื่อสร้างสิ่งaliasที่ตอบสนองจุดประสงค์นี้

สร้างนามแฝง

ในการสร้างนามแฝงเราจะใช้git config --global alias.<alias-name> <command>ในกรณีของเราฉันจะแนะนำสิ่งที่คล้ายกับสิ่งนี้

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

สิ่งนี้จะสร้างรายการใน.gitconfigไฟล์ส่วนกลางของคุณ(ซึ่งโดยปกติคุณจะพบได้ในโฮมไดเร็กทอรีของคุณ) หลังจากนี้คุณก็สามารถใช้git pushfเพื่อบังคับกับสัญญาเช่า

ทำให้มือของคุณสกปรก

หากคุณต้องการใช้คุณลักษณะตัวเอง แต่ไม่แน่ใจว่าจะเริ่มต้นเป็นครั้งแรกที่คุณควรจะดูที่เป็นเอกสารไดเรกทอรีในที่เก็บคอมไพล์ คุณสามารถดูหลักเกณฑ์การเขียนโค้ดและข้อมูลเกี่ยวกับวิธีการส่งแพตช์ได้ที่นี่

คุณสามารถค้นหาการเชื่อมโยงทั้งหมดเหล่านี้และอื่น ๆ บนเพจชุมชนอย่างเป็นทางการ


25
หมายเหตุเกี่ยวกับสิ่งนี้ไม่ใช่คุณลักษณะ: ข้อโต้แย้งทั่วไปในการเขียนคำสั่งมาตรฐานใหม่ ("push --force") คือคุณเคยชินกับคำสั่งเหล่านี้ลืมที่มาและวันหนึ่งบังเอิญใช้คำสั่งนี้ในระบบใหม่ เหมือน aliasing rmการrm -iใน .bashrc ของคุณ คุณจะลืมและลบไฟล์สำคัญบนเซิร์ฟเวอร์ในบางวัน ใช้นามแฝงของคุณเองไม่มีปัญหา :)
hraban

2
เกร็ดเล็กเกร็ดน้อยส่วนบุคคล / คำเตือน: ฉันลองใช้นามแฝงpushfแต่ตรวจสอบอีกครั้งเสมอว่าฉันไม่ได้ทำ a push -fเนื่องจากมันดูคล้ายกับนามแฝง สมาชิกในทีมบางคนใช้อย่างไรก็ตามโดยpush -fคิดว่านามแฝงเป็นเพียงชวเลขเพื่อความงามสำหรับมัน ในที่สุดเราได้เปลี่ยนรูปแบบที่ปลอดภัยกว่าเป็นpushflแทนและเลิกกังวลเกี่ยวกับเรื่องนี้
kelvin

31

ฉันกังวลว่าอาจลืมคุณสมบัติที่ดีนี้ในครั้งต่อไปที่ฉันต้องการ

Git 2.13 (Q2 2017) อธิบายว่าเหตุใดจึงไม่มีการ "ป้องกัน" ตัวเลือกการพุชนี้เนื่องจากแม้ว่าคุณจะไม่ลืมในgit pushระดับนั้น แต่ก็ยังอาจถูกเพิกเฉย

ดูกระทำ f17d642 (19 เมษายน 2017) โดยÆvar Arnfjord Bjarmason (avar )
(รวมโดยJunio C Hamano - gitster-ในการกระทำ 46bdfa3 , 26 เมษายน 2017)

push: เอกสารและทดสอบ--force-with-leaseด้วยรีโมทหลายตัว

เอกสารและการทดสอบสำหรับกรณีที่มีรีโมตสองตัวที่ชี้ไปยัง URL เดียวกันและการดึงข้อมูลพื้นหลังและภายหลังgit push --force-with-leaseไม่ควร clobber การอ้างอิงที่ไม่อัปเดตที่เราไม่ได้ดึงมา

ตัวแก้ไขบางตัวเช่น VSC ของ Microsoft มีคุณสมบัติในการดึงข้อมูลอัตโนมัติในพื้นหลังซึ่งจะข้ามการป้องกันที่นำเสนอโดย--force-with-lease&--force-with-lease=<refname>ตามที่ระบุไว้ในเอกสารประกอบที่เพิ่มไว้ที่นี่

ดังนั้นเอกสารในgit pushตอนนี้จึงประกอบด้วย:

หมายเหตุทั่วไปเกี่ยวกับความปลอดภัย: การจัดหาอ็อพชันนี้โดยไม่มีค่าที่คาดหวังเช่นเป็น--force-with-leaseหรือ--force-with-lease=<refname> โต้ตอบกับสิ่งใด ๆ ที่ทำงานโดยปริยายgit fetchบนรีโมตเพื่อผลักไปที่พื้นหลังเช่นgit fetch origin บนที่เก็บของคุณใน cronjob

การป้องกันที่มอบ--forceให้คือการตรวจสอบให้แน่ใจว่าการเปลี่ยนแปลงในภายหลังงานของคุณไม่ได้ขึ้นอยู่กับการไม่ยึดติด แต่สิ่งนี้จะพ่ายแพ้เล็กน้อยหากกระบวนการเบื้องหลังบางอย่างกำลังอัปเดตการอ้างอิงในพื้นหลัง เราไม่มีอะไรเลยนอกจากข้อมูลการติดตามระยะไกลที่จะนำไปใช้เพื่อเป็นข้อมูลอ้างอิงสำหรับการอ้างอิงที่คุณคาดว่าจะได้เห็นและยินดีที่จะปิดบัง

หากตัวแก้ไขของคุณหรือระบบอื่น ๆ กำลังทำงานgit fetchอยู่เบื้องหลังสำหรับคุณวิธีลดปัญหานี้คือเพียงแค่ตั้งค่ารีโมตอื่น:

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

ตอนนี้เมื่อกระบวนการพื้นหลังเรียกgit fetch originใช้การอ้างอิงorigin-pushจะไม่ได้รับการอัปเดตดังนั้นคำสั่งเช่น:

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

git fetch origin-pushจะล้มเหลวจนกว่าคุณจะทำงานด้วยตนเอง
แน่นอนว่าวิธีนี้พ่ายแพ้อย่างสิ้นเชิงกับสิ่งที่ทำงานgit fetch --allในกรณีนี้คุณต้องปิดการใช้งานหรือทำสิ่งที่น่าเบื่อเช่น:

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

เช่นสร้างbaseแท็กสำหรับเวอร์ชันของโค้ดอัปสตรีมที่คุณเคยเห็นและยินดีที่จะเขียนทับจากนั้นจึงเขียนประวัติใหม่และสุดท้ายบังคับให้พุชเปลี่ยนแปลงmasterหากเวอร์ชันรีโมตยังอยู่ที่baseไม่ว่าในเครื่องของคุณremotes/origin/masterจะอัปเดตเป็นอะไรใน พื้นหลัง.


30

วิธีแก้ปัญหาของฉันคือสร้างสคริปต์ Wrapper และใช้นามแฝงเพื่อให้ฉันใช้แทนของจริงgitเสมอ

เมื่อใดก็ตามที่ฉันพยายามฉันจะgit push -fเห็นสิ่งต่อไปนี้:

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

ข้อดีบางประการของสคริปต์นี้คือ:

  • มันฝึกให้ฉันใช้เป็นนิสัย--force-with-leaseดังนั้นฉันจะไม่จู้จี้เมื่อฉันทำผิด
  • ถ้าด้วยเหตุผลบางอย่างเราจำเป็นต้องบังคับผลักดันจริงๆgit push --forceก็จะได้ผล

วิธีการใช้งาน:

  1. สร้างสคริปต์แบบกำหนดเองที่จะส่งผ่านพารามิเตอร์ไปยังคอมไพล์ยกเว้น -f
  2. นามแฝงว่าสคริปต์ดังนั้นเราจึงใช้มันแทน git

คำแนะนำเหล่านี้ถือว่า Linux หรือ Mac รัน bash ฉันยังไม่ได้ลองใช้ zsh หรือ Windows แต่ฉันคิดว่ามันก็ใช้ได้เช่นกัน

~/.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 "$@"

ด้วยการเปลี่ยนแปลงเหล่านั้นให้รีสตาร์ทเทอร์มินัลของคุณและgitตอนนี้ควรได้รับความนิยมเมื่อคุณพยายามบังคับผลัก


18
ดูเหมือนสะดวก +1 อาจจะแทนที่ "hey idiot" ด้วย "hey คุณเป็นคนอ่อนโยน แต่เรียบง่าย" หรือพูดแบบนั้นก็ได้)
VonC


3

ฉันอยากจะเตือนว่าฉันไม่ควรใช้-fแต่ฉันไม่อยากถูกหลอกให้เชื่อ-fวิธี--force-with-leaseนั้น นี่คือสิ่งที่ฉันใช้:

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

เพิ่มไปของคุณ.bash_profile, หรือ.bashrc.zshrc


1

คุณสามารถสร้างฟังก์ชันทุบตีที่แทนที่gitและใช้--force-with-leaseแทน--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
}

หรือในหนึ่งบรรทัด:

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

เพียงเพิ่มลงใน~/.bashrcหรือ~/.zshrc.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.