บังคับใช้ "git push" เพื่อเขียนทับไฟล์ระยะไกล


766

ฉันต้องการที่จะผลักดันไฟล์ท้องถิ่นของฉันและมีพวกเขาใน repo ระยะไกลโดยไม่ต้องจัดการกับความขัดแย้งผสาน ฉันแค่ต้องการให้รุ่นในพื้นที่ของฉันมีลำดับความสำคัญสูงกว่ารีโมท

ฉันจะทำสิ่งนี้กับ Git ได้อย่างไร


106
ไม่git push origin --forceได้ผลสำหรับคุณ?


ไม่ชัดเจนหากคุณต้องการแทนที่ไฟล์. git หรือสำเนาการทำงานที่เกี่ยวข้องเท่านั้น ถ้าเป็นที่เก็บ git ก็คือคำตอบ git push หากคุณต้องการอัปเดตสำเนาการทำงานระยะไกลคุณต้องใช้เบ็ดหลังรับ
Pierre-Olivier Vares

@ ไมค์ที่เหมาะกับฉันด้วยเหตุผลบางอย่าง ... สงสัยว่าเกิดอะไรขึ้นกับ OP

สาเหตุที่เป็นไปได้คือการบังคับการกดปุ่มไม่ทำงานคืออาจปิดการใช้งานอย่างชัดแจ้งบน repo ระยะไกล (เพื่อให้แน่ใจว่าไม่มีอะไรหลงหายเนื่องจากผู้สนับสนุนที่งี่เง่าและ / หรือเป็นอันตราย): ใช้config receive.denyNonFastforwardsเพื่อค้นหา
Frank Nocke

คำตอบ:


1085

คุณควรจะสามารถบังคับให้มีการแก้ไขในพื้นที่ของคุณไปยัง repo ระยะไกลได้โดยใช้

git push -f <remote> <branch>

(เช่นgit push -f origin master) ออกนอก<remote>และจะบังคับให้ผลักดันสาขาในประเทศทั้งหมดที่มีการตั้ง<branch>--set-upstream

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

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

อัปเดต 2 : เนื่องจากจำนวนผู้ชมที่เพิ่มขึ้นฉันต้องการเพิ่มข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่ต้องทำเมื่อคุณupstreamประสบปัญหา

สมมติว่าฉันได้ลอกแบบ repo ของคุณและเพิ่มคอมมิชชันสองสามอย่างเช่น:

            D ---- E
           /
A ---- B ---- C การพัฒนา

แต่ต่อมาdevelopmentสาขาถูกตีด้วยrebaseซึ่งจะทำให้ฉันได้รับข้อผิดพลาดเช่นเมื่อฉันทำงานgit pull:

การแกะวัตถุออก: 100% (3/3) เสร็จแล้ว
จาก <repo-location>
 * การพัฒนาสาขา -> FETCH_HEAD
การผสาน <files> อัตโนมัติ
ความขัดแย้ง (เนื้อหา): รวมความขัดแย้งใน <locations>
การผสานอัตโนมัติล้มเหลว แก้ไขข้อขัดแย้งแล้วส่งผลลัพธ์

ที่นี่ฉันสามารถแก้ไขข้อขัดแย้งและcommitแต่นั่นจะทำให้ฉันมีประวัติความเป็นมาที่น่าเกลียดจริงๆ:

       C ---- D ---- E ---- F หัวข้อ
      / /
A ---- B -------------- C 'การพัฒนา

มันอาจดูล่อลวงที่จะใช้git pull --forceแต่ต้องระวังเพราะมันจะทำให้คุณหลงผิด:

            D ---- E

A ---- B ---- C 'การพัฒนา

git pull --rebaseดังนั้นอาจจะเป็นตัวเลือกที่ดีที่สุดคือการทำ นี้จะต้องให้ฉันแก้ปัญหาความขัดแย้งใด ๆ เช่นก่อน git rebase --continueแต่สำหรับขั้นตอนแทนการกระทำฉันจะใช้ในแต่ละ ในท้ายที่สุดประวัติศาสตร์การกระทำจะดูดีขึ้นมาก:

            หัวข้อ D '--- E'
           /
A ---- B ---- C 'การพัฒนา

อัปเดต 3:คุณยังสามารถใช้--force-with-leaseตัวเลือกเป็นแรงผลักดัน "ปลอดภัย" ดังที่ Cupcake กล่าวไว้ในคำตอบของเขา :

การบังคับใช้การกดปุ่ม "Lease" ทำให้การกดแบบบังคับนั้นล้มเหลวหากมีคอมมิชชันใหม่ในรีโมตที่คุณไม่ได้คาดหวัง (ในทางเทคนิคหากคุณยังไม่ได้ทำการดึงพวกมันเข้าสาขาการติดตามระยะไกล) ซึ่งมีประโยชน์ถ้า คุณไม่ต้องการเขียนทับคำสั่งของคนอื่นโดยไม่ตั้งใจซึ่งคุณยังไม่รู้และคุณต้องการเขียนทับของคุณเอง:

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

คุณสามารถเรียนรู้รายละเอียดเพิ่มเติมเกี่ยวกับวิธีใช้งานได้--force-with-leaseโดยอ่านสิ่งต่อไปนี้:


5
เนื่องจากนี่เป็นคำตอบที่เลือกฉันจะแสดงความคิดเห็นที่นี่ การใช้กำลังไม่ใช่ปัญหาเมื่อทำงานด้วยตัวเอง ตัวอย่างเช่นโฮสต์คลาวด์ของฉันเริ่มต้นด้วยคอมไพล์ของตัวเอง ถ้าฉันทำงานในพื้นที่และสร้างโครงการและฉันต้องการวางไว้บนโฮสต์คลาวด์ของฉัน (OpenShift) ฉันมีสองโครงการคอมไพล์แยกกัน ท้องถิ่นและ OpenShift ของฉัน ฉันได้รับในท้องที่ของฉันตามที่ต้องการ แต่ตอนนี้ต้องการดูตัวอย่างบน OpenShift ของฉัน จากนั้นคุณกดไปที่ OpenShift เป็นครั้งแรกโดยใช้การ-fตั้งค่าสถานะ เป็นหลักวาง git ท้องถิ่นของคุณบน OpenShift
ลุย

128

คุณต้องการบังคับให้กด

สิ่งที่คุณต้องการทำคือบังคับให้สาขาในพื้นที่ของคุณต้องเขียนทับรีโมต

หากคุณต้องการคำอธิบายโดยละเอียดเพิ่มเติมของแต่ละคำสั่งต่อไปนี้ให้ดูที่ส่วนรายละเอียดของฉันด้านล่าง คุณมี 4 ตัวเลือกที่แตกต่างกันสำหรับการบังคับใช้ 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

หากคุณต้องการคำอธิบายโดยละเอียดเพิ่มเติมของแต่ละคำสั่งโปรดดูหัวข้อคำตอบแบบยาวของฉันด้านล่าง

คำเตือน: การบังคับให้กดจะเขียนทับสาขาระยะไกลด้วยสถานะของสาขาที่คุณกำลังกด ตรวจสอบให้แน่ใจว่านี่คือสิ่งที่คุณต้องการทำจริง ๆ ก่อนที่จะใช้มิฉะนั้นคุณอาจเขียนทับการกระทำที่คุณต้องการเก็บไว้

บังคับให้กดรายละเอียด

ระบุระยะไกลและสาขา

คุณสามารถระบุสาขาเฉพาะและรีโมตได้อย่างสมบูรณ์ การ-fตั้งค่าสถานะเป็นรุ่นสั้น ๆ ของ--force

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

ข้ามสาขา

เมื่อละเว้นสาขาที่จะผลักสาขาแล้ว Git จะคิดตามการตั้งค่า config ของคุณ ในรุ่น Git หลังจาก 2.0 Repo ใหม่จะมีการตั้งค่าเริ่มต้นเพื่อผลักดันสาขาที่เช็คเอาท์ในปัจจุบัน:

git push <remote> --force

ในขณะที่ก่อนหน้า 2.0, repos ใหม่จะมีการตั้งค่าเริ่มต้นเพื่อผลักดันหลายสาขาท้องถิ่น การตั้งค่าที่เป็นปัญหาremote.<remote>.pushและpush.defaultการตั้งค่า (ดูด้านล่าง)

เว้นระยะไกลและสาขา

เมื่อละเว้นทั้งระยะไกลและสาขาแล้วพฤติกรรมของ just git push --forceจะถูกกำหนดโดยpush.defaultการตั้งค่า Git ของคุณ:

git push --force
  • ในฐานะของ Git 2.0 การตั้งค่าเริ่มต้นsimpleโดยทั่วไปแล้วจะผลักสาขาปัจจุบันของคุณไปยังส่วนรีโมตรีสตรีม ระยะไกลจะถูกกำหนดโดยการbranch.<remote>.remoteตั้งค่าของสาขาและค่าเริ่มต้นไปที่ repo กำเนิดเป็นอย่างอื่น

  • ก่อน Git เวอร์ชั่น 2.0 การตั้งค่าเริ่มต้นmatchingโดยทั่วไปเพียงแค่ผลักสาขาในท้องถิ่นของคุณทั้งหมดไปยังสาขาที่มีชื่อเดียวกันบนรีโมท (ซึ่งเป็นค่าเริ่มต้นที่มา)

คุณสามารถอ่านเพิ่มเติมpush.defaultการตั้งค่าโดยการอ่านgit help configหรือรุ่นออนไลน์ของ Git-config (1) หน้าคู่มือการใช้

บังคับผลักดันให้ปลอดภัยยิ่งขึ้นด้วย --force-with-lease

การบังคับใช้การกดปุ่ม "Lease" ทำให้การกดแบบบังคับนั้นล้มเหลวหากมีคอมมิชชันใหม่ในรีโมตที่คุณไม่ได้คาดหวัง (ในทางเทคนิคหากคุณยังไม่ได้ทำการดึงพวกมันเข้าสาขาการติดตามระยะไกล) ซึ่งมีประโยชน์ถ้า คุณไม่ต้องการเขียนทับคำสั่งของคนอื่นโดยไม่ตั้งใจซึ่งคุณยังไม่รู้และคุณต้องการเขียนทับของคุณเอง:

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

คุณสามารถเรียนรู้รายละเอียดเพิ่มเติมเกี่ยวกับวิธีใช้งานได้--force-with-leaseโดยอ่านสิ่งต่อไปนี้:


คุณพูดถูก แต่สิ่งนี้ควรใช้ในสถานการณ์พิเศษเท่านั้น
Scott Berrevoets

1
@ScottBerrevoets " ฉันต้องการที่จะผลักดันสิ่งที่ฉันมีและปล่อยให้มันเขียนทับจากระยะไกลมากกว่าที่จะรวมเข้าด้วยกัน " ฉันให้ OP อย่างที่เขาขอ

ฉันรู้ แต่ OP อาจไม่ได้ตระหนักถึงผลของการทำเช่นนี้ คุณตอบคำถามทางเทคนิค แต่ฉันคิดว่าคำเตือนว่าอย่าทำเช่นนี้ไม่ได้เกิดขึ้น
Scott Berrevoets

1
@ScottBerrevoets ฉันพยายามให้ผู้ดูแลรวมคำตอบของฉันเข้ากับบัญญัติเพราะฉันพูดถึง--force-with-leaseตัวเลือกใหม่;)

1
FYI: ผสานจากstackoverflow.com/questions/24768330/…
Shog9

32

ตัวเลือกอื่น (เพื่อหลีกเลี่ยงการกดทับซึ่งอาจเป็นปัญหาสำหรับผู้มีส่วนร่วมคนอื่น ๆ ) คือ:

  • ใส่ความมุ่งมั่นใหม่ของคุณในสาขาเฉพาะ
  • รีเซ็ตของคุณmasterในorigin/master
  • รวมสาขาเฉพาะของคุณไปยังmasterรักษาคอมมิชชันจากสาขาเฉพาะ (หมายถึงการสร้างการแก้ไขใหม่ด้านบนmasterซึ่งจะสะท้อนสาขาเฉพาะของคุณ)
    โปรดดูที่ " คำสั่งคอมไพล์สำหรับการทำสาขาหนึ่งเหมือนที่อื่น " git merge --strategy=theirsสำหรับกลยุทธ์ไปสู่การจำลอง

ด้วยวิธีนี้คุณสามารถผลักต้นแบบไปยังรีโมทโดยไม่ต้องบังคับอะไร


ผลลัพธ์แตกต่างจาก "push -force" อย่างไร
alexkovelsky

6
@alexkovelsky การกดใด ๆ ที่ถูกบังคับจะเขียนประวัติอีกครั้งบังคับให้ผู้ใช้ repo คนอื่น ๆ เพื่อรีเซ็ต repo ในท้องถิ่นของตนเพื่อให้ตรงกับคอมมิชชันที่เพิ่งผลัก วิธีการนี้สร้างคอมมิทใหม่เท่านั้นและไม่จำเป็นต้องมีการบังคับ
VonC

1
ฉันขอแนะนำให้คุณเพิ่มหัวข้อในคำตอบของคุณ: "คุณไม่ต้องการบังคับให้กด" :)
alexkovelsky

@alexkovelsky จุดที่ดี ฉันได้แก้ไขคำตอบแล้ว
VonC

4

git push -f เป็นสิ่งที่ทำลายล้างเล็กน้อยเนื่องจากจะรีเซ็ตการเปลี่ยนแปลงระยะไกลใด ๆ ที่ทำโดยบุคคลอื่นในทีม ตัวเลือกที่ปลอดภัยคือ {git push --force-with-lease}

สิ่งที่ {--force-with-lease} ไม่ปฏิเสธที่จะอัปเดตสาขาเว้นแต่ว่าเป็นสถานะที่เราคาดหวัง เช่นไม่มีใครอัปเดตสาขาต้นน้ำ ในทางปฏิบัติงานนี้โดยการตรวจสอบว่าการอ้างอิงต้นน้ำเป็นสิ่งที่เราคาดหวังเพราะการอ้างอิงนั้นแฮชและเข้ารหัสโซ่ของผู้ปกครองโดยปริยายในคุณค่าของพวกเขา คุณสามารถบอก {--force-with-lease} อย่างแน่นอนว่าต้องตรวจสอบอะไร แต่โดยค่าเริ่มต้นจะตรวจสอบการอ้างอิงระยะไกลปัจจุบัน สิ่งนี้หมายความว่าในทางปฏิบัติคือเมื่ออลิซอัปเดตสาขาของเธอและผลักดันมันไปยังที่เก็บระยะไกลหัวอ้างอิงของสาขาจะได้รับการอัปเดต ทีนี้เว้นแต่ว่าบ๊อบจะดึงจากระยะไกลการอ้างอิงในท้องถิ่นของเขากับรีโมทจะล้าสมัย เมื่อเขาไปกดโดยใช้ {--force-with-lease} คอมไพล์จะตรวจสอบการอ้างอิงท้องถิ่นกับรีโมตใหม่และปฏิเสธที่จะบังคับให้กด {--force-with-lease} ได้อย่างมีประสิทธิภาพช่วยให้คุณสามารถบังคับให้กดได้หากไม่มีใครผลักดันการเปลี่ยนแปลงขึ้นสู่ระยะไกลในระหว่างกาล มันคือ {- บังคับ} พร้อมกับคาดเข็มขัดนิรภัย



0

ขั้นตอนง่าย ๆ โดยใช้ tortoisegit

GIT ให้ไฟล์ในพื้นที่กระทำและผลักดันเข้าไปในพื้นที่เก็บข้อมูลคอมไพล์

ขั้นตอน:

1) stash เปลี่ยน ชื่อที่เก็บ

2) การดึง

3) ป๊อปสะสม

4) กระทำ 1 ไฟล์หรือมากกว่าและให้กระทำการเปลี่ยนแปลงผู้เขียนคำอธิบายชุดและวันที่

5) การผลักดัน

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