ฉันจะบังคับให้ "git pull" เขียนทับไฟล์ในเครื่องได้อย่างไร


7182

ฉันจะบังคับให้เขียนทับไฟล์ภายในเครื่องได้git pullอย่างไร?

สถานการณ์มีดังต่อไปนี้:

  • สมาชิกในทีมกำลังแก้ไขแม่แบบสำหรับเว็บไซต์ที่เรากำลังทำงาน
  • พวกเขากำลังเพิ่มภาพบางส่วนไปยังไดเรกทอรีภาพ (แต่ลืมที่จะเพิ่มพวกเขาภายใต้การควบคุมแหล่งที่มา)
  • พวกเขากำลังส่งภาพทางไปรษณีย์มาหาฉันทีหลัง
  • ฉันกำลังเพิ่มภาพภายใต้การควบคุมของแหล่งที่มาและผลักพวกเขาไปที่ GitHub พร้อมกับการเปลี่ยนแปลงอื่น ๆ
  • พวกเขาไม่สามารถดึงการอัปเดตจาก GitHub ได้เพราะ Git ไม่ต้องการเขียนทับไฟล์

นี่เป็นข้อผิดพลาดที่ฉันได้รับ:

ข้อผิดพลาด: ไฟล์ต้นไม้ทำงานที่ไม่ได้ติดตาม 'สาธารณะ / images / icon.gif' จะถูกเขียนทับโดยการรวม

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


17
ใครก็ตามที่อ่านสิ่งนี้ซึ่งคิดว่าพวกเขาอาจสูญเสียไฟล์ฉันอยู่ในตำแหน่งนี้และพบว่าบัฟเฟอร์ของ Sublime Text ได้ช่วยฉัน - ถ้าฉันกำลังทำงานบางอย่างแล้วตั้งใจลบทุกอย่างโดยพยายามแก้ปัญหาที่คล้ายกันนี้หรือโดยใช้ คำตอบสำหรับคำถามนี้และมีไฟล์ที่เปิดใน Sublime (ซึ่งมีโอกาสดี) จากนั้นไฟล์จะยังคงมี Sublime ไม่ว่าจะที่นั่นหรือในประวัติศาสตร์การเลิกทำ
Toni Leigh

62
git reset --hard origin/branch_to_overwrite
Andrew Atkinson

1
โดยทั่วไปจะทำเพียงดึงจากการพัฒนาหลังจากการชำระเงินเริ่มต้น -b ทำงานของคุณแล้วจึงกลับมาใหม่
ldgorman

1
คำตอบสั้น ๆ : ลบและสร้างสาขาใหม่ 1. ลบสาขา: git branch <branch> -D2. รีเซ็ตเป็นคอมมิทก่อนการขัดแย้ง: git reset <commit> --hard3. สร้างสาขาใหม่อีกครั้ง: git branch <branch>4. ตั้งค่าการติดตามไปที่เซิร์ฟเวอร์: git --set-upstream-to=origin/<branch> <branch> 5. Pull: git pull`
Nino Filiu

1
ในการเปลี่ยนตอนจบของ CRLF เป็น LF (เริ่มต้นใหม่ทั้งหมด)git config core.autocrlf false; git ls-files -z | xargs -0 rm; git checkout .
Chloe

คำตอบ:


10034

สำคัญ: หากคุณมีการเปลี่ยนแปลงในท้องถิ่นการเปลี่ยนแปลงเหล่านั้นจะหายไป ไม่--hardว่าจะมีหรือไม่มีตัวเลือกการกระทำในท้องถิ่นใด ๆ ที่ไม่ได้ผลักจะหายไป [*]

หากคุณมีไฟล์ใด ๆ ที่ไม่ได้ติดตามโดย Git (เช่นเนื้อหาผู้ใช้ที่อัปโหลด) ไฟล์เหล่านี้จะไม่ได้รับผลกระทบ


ฉันคิดว่านี่เป็นวิธีที่ถูกต้อง:

git fetch --all

จากนั้นคุณมีสองตัวเลือก:

git reset --hard origin/master

หรือถ้าคุณอยู่ในสาขาอื่น:

git reset --hard origin/<branch_name>

คำอธิบาย:

git fetch ดาวน์โหลดล่าสุดจากระยะไกลโดยไม่พยายามผสานหรือรีบูตอะไร

จากนั้นgit resetรีเซ็ตสาขาหลักเป็นสิ่งที่คุณดึงมา --hardตัวเลือกการเปลี่ยนแปลงไฟล์ทั้งหมดในต้นไม้การทำงานของคุณเพื่อให้ตรงกับไฟล์ในorigin/master


รักษาความมุ่งมั่นในท้องถิ่นปัจจุบัน

[*] : น่าสังเกตว่าเป็นไปได้ที่จะรักษาคอมมิชชันปัจจุบันโดยสร้างสาขาจากmasterก่อนทำการรีเซ็ต:

git checkout master
git branch new-branch-to-save-current-commits
git fetch --all
git reset --hard origin/master

new-branch-to-save-current-commitsหลังจากนี้ทั้งหมดของกระทำเก่าจะถูกเก็บไว้ใน

การเปลี่ยนแปลงที่ไม่ผูกมัด

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

git stash

จากนั้นจึงนำการเปลี่ยนแปลงที่ไม่มีข้อผูกมัดไปใช้ใหม่:

git stash pop

14
ระวัง! หากคุณมีข้อผูกพันที่ไม่ได้ชำระในท้องถิ่นจะเป็นการลบออกจากสาขาของคุณ! วิธีการแก้ปัญหานี้จะเก็บไฟล์ที่ไม่ได้ติดตามไม่ได้อยู่ในพื้นที่เก็บข้อมูลเหมือนเดิม แต่จะเขียนทับทุกอย่างอื่น
Matthijs P

479
มันเป็นคำถามยอดนิยมดังนั้นฉันต้องการที่จะชี้แจงเกี่ยวกับความคิดเห็นด้านบนที่นี่ ฉันเพิ่งดำเนินการคำสั่งตามที่อธิบายไว้ในคำตอบนี้และมันไม่ได้ลบไฟล์ทั้งหมดในเครื่อง เฉพาะไฟล์ที่ถูกติดตามจากระยะไกลเท่านั้นที่ถูกเขียนทับและไฟล์ในเครื่องทั้งหมดที่อยู่ที่นี่ถูกทิ้งไว้โดยไม่ถูกแตะต้อง
Red

14
ในกรณีที่คุณดึงจาก repo ที่มีชื่อสาขาระยะไกลต่างจาก "master" ให้ใช้git reset --hard origin/branch-name
Nerrve

97
ด้วยจำนวน upvotes สำหรับคำถามและคำตอบนี้ฉันคิดว่าคอมไพล์ควรรวมคำสั่งเช่นgit pull -f
Sophivorus

7
คอมมิชชันที่ไม่ได้ถูกพุชก่อนที่ฮาร์ดรีเซ็ตสามารถกู้คืนได้โดยใช้git reflogซึ่งแสดงรายการการคอมมิททั้งหมดรวมถึงคอมมิชชันที่ไม่มีฐาน จนกว่าคุณจะล้างสำเนาในเครื่องของคุณโดยใช้git gcข้อมูลทั้งหมดจะหายไป
Koen

933

ลองสิ่งนี้:

git reset --hard HEAD
git pull

มันควรทำสิ่งที่คุณต้องการ


16
ฉันทำไปแล้วและไฟล์ในเครื่องที่ไม่ได้อยู่ใน repo เหลืออยู่บนดิสก์
Piotr Owsiak

26
ฉันไม่คิดว่ามันถูกต้อง ด้านบนจะทำการผสานไม่ใช่เขียนทับซึ่งได้รับการร้องขอในคำถาม: "จะบังคับให้ git เขียนทับได้อย่างไร" ฉันไม่มีคำตอบฉันกำลังมองหามัน .. ในขณะนี้ฉันเปลี่ยนเป็นสาขาด้วยรหัสที่ฉันต้องการเก็บ "git checkout BranchWithCodeToKeep" จากนั้นทำ "git branch -D BranchToOverwrite" และสุดท้าย "git checkout -b BranchToOverwrite" ตอนนี้คุณจะมีรหัสที่แน่นอนจาก BranchWithCodeToKeep ใน BranchToOverwrite ของสาขาโดยไม่ต้องทำการผสาน
felbus

252
แทนที่จะรวมกันโดยใช้ 'git pull' ลองใช้ git fetch - ทั้งหมดตามด้วย 'git reset - แหล่งกำเนิด / มาสเตอร์ที่ยากลำบาก'
Lloyd Moore

5
ใช่วิธีการแก้ปัญหา @lloydmoore เหมาะกับฉัน สามารถทำได้ด้วยการเป็นคำตอบมากกว่าแค่ความคิดเห็น
Max Williams

2
การดำเนินการนี้จะรีเซ็ตการเปลี่ยนแปลงปัจจุบันกลับไปสู่การดึงข้อมูลล่าสุดของสาขา จากนั้น git pull จะรวมการเปลี่ยนแปลงจากสาขาล่าสุด นี่เป็นสิ่งที่ฉันต้องการให้ทำ .. ขอบคุณ!
Codeversed

459

คำเตือน: git cleanลบไฟล์ / ไดเรกทอรีที่ไม่ได้ติดตามทั้งหมดของคุณและไม่สามารถยกเลิกได้


บางครั้งก็clean -fไม่ช่วย ในกรณีที่คุณมีเส้นทางที่ไม่ได้ติดตามตัวเลือก -d ต้องการ:

# WARNING: this can't be undone!

git reset --hard HEAD
git clean -f -d
git pull

คำเตือน: git cleanลบไฟล์ / ไดเรกทอรีที่ไม่ได้ติดตามทั้งหมดของคุณและไม่สามารถยกเลิกได้

พิจารณาใช้-n( --dry-run) ธงก่อน นี่จะแสดงสิ่งที่จะถูกลบโดยไม่ลบอะไรเลย:

git clean -n -f -d

ตัวอย่างผลลัพธ์:

Would remove untracked-file-1.txt
Would remove untracked-file-2.txt
Would remove untracked/folder
...

33
ยอดเยี่ยม ... รีบจัดการกับ repo dotfiles ของฉัน ... ในไดเรกทอรีบ้านของฉัน ดีที่ฉันไม่มีอะไรสำคัญเลยที่นั่น ...
Lauri

7
ฉันคิดว่าคำอธิบายสถานการณ์ทำให้เห็นชัดเจนว่าเขาไม่ต้องการทิ้งเนื้อหา สิ่งที่เขาต้องการคือหยุดการเขียนทับไฟล์ทับ @ Lauri สิ่งนี้ไม่ควรเกิดขึ้นกับคุณ น่าเสียดายที่คนดูเหมือนจะเข้าใจผิดในสาระสำคัญของคำอธิบายสถานการณ์ - ดูคำแนะนำของฉัน
เม่น

19
ในที่สุด git clean -f -d มีประโยชน์เมื่อทำให้การทำความสะอาดล้มเหลวในการทำความสะอาดทุกอย่าง
earthmeLon

7
@crizCraig จนกว่าพวกเขาจะถูกเพิ่มเข้ามา.gitignore
Bleeding Fingers

5
@earthmeLon git clean -dfxเพื่อที่คุณอาจต้องการ -xละเว้น .gitignore โดยทั่วไปผลิตภัณฑ์สร้างของคุณจะอยู่ใน. gignignore
พอลเดรเปอร์

384

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

ก่อนอื่นให้กระทำการเปลี่ยนแปลงของคุณ

 git add *
 git commit -a -m "local file server commit message"

จากนั้นเรียกการเปลี่ยนแปลงและเขียนทับหากมีข้อขัดแย้ง

 git fetch origin master
 git merge -s recursive -X theirs origin/master

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


56
นี่คือคำตอบที่ดีที่สุดที่ฉันเคยเห็น ฉันไม่ได้ลอง แต่ไม่เหมือนคำตอบอื่น ๆ นี่ไม่ได้พยายามที่จะทำไฟล์ที่ไม่ได้ติดตามทั้งหมดซึ่งเป็นอันตรายอย่างยิ่งด้วยเหตุผลที่ชัดเจน
huyz

5
Ditto - มันใช้งานได้สำหรับฉันเมื่อทำการผสานขนาดใหญ่มาก (คำขอดึง GitHub) ที่ฉันแค่อยากจะยอมรับมันทั้งหมดบนสิ่งที่ฉันมี คำตอบที่ดี! ในกรณีของฉันคำสั่งสองคำสั่งสุดท้ายคือ: 1) get fetch other-repo; 2)git merge -s recursive -X theirs other-repo/master
quux00

2
สิ่งนี้จะเขียนทับความขัดแย้งใด ๆ กับไฟล์ที่เก็บและไม่ใช่ไฟล์โลคัลของคุณใช่ไหม?
นาธานเอฟ

2
คำตอบที่ดีที่สุด คำตอบที่ได้รับการยอมรับสูงสุดทำให้ฉันอยู่ในหัวของฉันบนหัวเดี่ยว ฉันเปลี่ยนกลับเป็นสาขาต้นแบบในท้องถิ่นและวิ่งไปgit merge -X theirs origin/master
เตอร์

2
ปัญหากับคำตอบ (ยอดเยี่ยม) นี้คือมันเพิ่มไฟล์ในเครื่องทั้งหมดซึ่งบางครั้งอาจไม่เป็นสิ่งที่คุณต้องการ คุณอาจต้องการเพิ่มไฟล์เฉพาะที่ถูกตัดออก แต่สิ่งที่ดีที่สุดเกี่ยวกับเรื่องนี้คือทำให้เขาทำในสิ่งที่เขาควรทำ - เพิ่มพวกเขาในพื้นที่ คุณอาจไม่ต้องการกลยุทธ์ -X เพราะมันเป็นภาพเดียวกัน ในความเป็นจริงฉันขอแนะนำให้ออกในตอนแรกเพียงเพื่อดูว่ามีความผิดปกติใด ๆ หรือไม่และเพิ่มเข้าไปหากมีหลังจากตรวจสอบว่า 'พวกเขา' เป็นตัวเลือกที่ถูกต้องเสมอ แต่ฉันก็หวาดระแวง
Bob Kerns

279

แทนที่จะทำ:

git fetch --all
git reset --hard origin/master

ฉันแนะนำให้ทำต่อไปนี้:

git fetch origin master
git reset --hard origin/master

ไม่จำเป็นต้องดึงรีโมตและสาขาทั้งหมดหากคุณจะรีเซ็ตเป็นสาขาต้นทาง / สาขาหลักใช่ไหม


3
คำตอบของคุณคือสิ่งที่คุณต้องการสำหรับตัวแทนของคุณ ฉันต้องถามสิ่งนี้จะลบไฟล์ที่ไม่ได้ติดตามทั้งหมดหรือไม่
Nicolas De Jay

5
ใช่ตัวแทนส่วนใหญ่ของฉันมาจากที่นี่ :) ซึ่งจะลบไฟล์ที่ไม่ได้ติดตามทั้งหมด บางสิ่งที่ฉันลืมไปแล้วและได้รับการเตือนอย่างเจ็บปวดเมื่อ 2 วันที่ผ่านมา ...
Johanneke

1
ดูความคิดเห็นเกี่ยวกับคำตอบอื่น ๆ นี้: stackoverflow.com/a/8888015/2151700
Johanneke

สิ่งนี้ไม่ได้ลบไฟล์ที่ไม่ได้ติดตามของฉัน ซึ่งเป็นสิ่งที่ฉันคาดหวัง มีเหตุผลสำหรับคนบางคนใช่หรือไม่?
arichards

ไฟล์ที่ไม่ได้ติดตามไม่ได้รับผลกระทบจากการรีเซ็ต git หากคุณต้องการให้พวกเขาถูกลบออกเช่นกันทำgit add .ก่อนก่อนgit reset --hard
Johanneke

131

ดูเหมือนว่าวิธีที่ดีที่สุดคือก่อนอื่น:

git clean

หากต้องการลบไฟล์ที่ไม่ได้ติดตามทั้งหมดแล้วดำเนินการต่อตามปกติgit pull...


4
ฉันพยายามใช้ "git clean" เพื่อแก้ปัญหาเดียวกัน แต่ไม่สามารถแก้ไขได้ สถานะ git กล่าวว่า "สาขาและ 'ต้นกำเนิด / หลัก' ของคุณแยกจากกัน # และมีการกระทำที่แตกต่างกัน 2 และ 9 รายการตามลำดับ" และ git pull พูดอะไรที่คล้ายกับสิ่งที่คุณมีด้านบน
slacy

43
คอมไพล์สะอาดเป็นเครื่องมือที่ค่อนข้างทื่อและสามารถทิ้งสิ่งต่าง ๆ มากมายที่คุณอาจต้องการเก็บไว้ ดีกว่าที่จะลบหรือเปลี่ยนชื่อไฟล์ที่คอมไพล์บ่นเกี่ยวกับจนกว่าจะดึงประสบความสำเร็จ
Neil Mayhew

2
ฉันไม่คิดว่างานนี้โดยทั่วไป ไม่มีวิธีในการทำรีโมตคอมไพล์ git ผ่านการบังคับ git pull หรือไม่?
mathtick

10
@mathick:git fetch origin && git reset --hard origin/master
Arrowmaster

3
คือgit cleanคำตอบที่ดีที่สุดที่นี่? ดูเหมือนว่าการลบไฟล์ไม่จำเป็นต้องเป็นสิ่งที่ OP ต้องการ พวกเขาถามหา 'การเขียนทับไฟล์ในเครื่อง' ไม่ใช่การลบ
JohnAllen

111

คำเตือนการทำเช่นนี้จะเป็นการลบไฟล์ของคุณอย่างถาวรหากคุณมีรายการไดเร็กทอรี / * ในไฟล์ gitignore ของคุณ

คำตอบบางอย่างดูเหมือนจะแย่มาก แย่มากในแง่ของสิ่งที่เกิดขึ้นกับ @Lauri โดยทำตามคำแนะนำของ David Avsajanishvili

ค่อนข้าง (git> v1.7.6):

git stash --include-untracked
git pull

หลังจากนั้นคุณสามารถทำความสะอาดประวัติสะสม

ด้วยตนเองแบบหนึ่งต่อหนึ่ง:

$ git stash list
stash@{0}: WIP on <branch>: ...
stash@{1}: WIP on <branch>: ...

$ git stash drop stash@{0}
$ git stash drop stash@{1}

อย่างไร้ความปราณีทั้งหมดในครั้งเดียว:

$ git stash clear

แน่นอนถ้าคุณต้องการกลับไปที่สิ่งที่คุณซ่อนไว้:

$ git stash list
...
$ git stash apply stash@{5}

2
ไม่ฉันไม่คิดอย่างนั้น Stashing เพียงแค่ย้ายไฟล์ที่ไม่มีข้อผูกมัดออกไป ข้างต้นยังย้าย (หยุด) ไฟล์ที่คอมไพล์ไม่ได้ติดตาม นี่เป็นการป้องกันไฟล์ที่ถูกเพิ่มลงในรีโมตซึ่งยังไม่ได้ดึงลงไปในเครื่องของคุณ - แต่ไฟล์ที่คุณสร้าง (!) - จะถูกดึงลงมา ทั้งหมดโดยไม่ทำลายงานปราศจากข้อผูกมัด หวังว่าจะสมเหตุสมผล
เม่น

3
หากคุณไม่มี 1.7.6 คุณสามารถเลียนแบบได้--include-untrackedง่ายๆโดยการgit addซื้อ repo ทั้งหมดของคุณชั่วคราวจากนั้นหยุดทันที
nategood

3
ฉันเห็นด้วยกับเม่น หากคุณทำคำตอบที่ได้รับความนิยมที่นี่คุณมีแนวโน้มที่จะพบว่าคุณถูกฆ่าโดยไม่ได้ตั้งใจหลายสิ่งที่คุณไม่ต้องการสูญเสีย
Guardius

1
ฉันมีไฟล์ที่ไม่ได้ติดตามอื่น ๆ นอกเหนือจากไฟล์ที่ต้องการผสาน / เขียนทับดังนั้นโซลูชันนี้ทำงานได้ดีที่สุด git stash applyนำไฟล์ที่ไม่ได้ติดตามทั้งหมดของฉันกลับมาด้วยข้อยกเว้น (ถูกต้อง) ของไฟล์ที่ผสานได้สร้างไว้แล้ว: "มีอยู่แล้วไม่มีการชำระเงิน" ทำงานได้อย่างสมบูรณ์แบบ
BigBlueHat

2
นี่คือคำตอบที่สะอาดที่สุดและควรเป็นคำตอบที่ยอมรับได้ git stash -uเพื่อบันทึกการพิมพ์บางอย่างที่คุณสามารถใช้แบบฟอร์มสั้น:
ccpizza

93

คุณอาจพบว่าคำสั่งนี้มีประโยชน์ในการทิ้งการเปลี่ยนแปลงในเครื่อง:

git checkout <your-branch> -f

จากนั้นทำการล้างข้อมูล (ลบไฟล์ที่ไม่ได้ติดตามจากแผนผังการทำงาน):

git clean -f

หากคุณต้องการลบไดเรกทอรีที่ไม่ได้ติดตามนอกเหนือจากไฟล์ที่ไม่ได้ติดตาม:

git clean -fd

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

3
แม้ว่าคำตอบนั้นอาจไม่ตรงกับคำอธิบายที่แน่นอน แต่ก็ยังช่วยให้ฉันไม่หงุดหงิดกับคอมไพล์ twiddling กับผลตอบแทนการขนส่ง (เหตุการณ์ที่มี autocrlf เท็จ) เมื่อรีเซ็ต git - HEAD HEAD จะไม่ทิ้งคุณไว้กับไฟล์ "no" ที่ถูกแก้ไขแฟล็ก "-f" เหล่านี้มีประโยชน์มาก ขอบคุณมัด
Kellindil


61

สิ่งเดียวที่ใช้ได้ผลสำหรับฉันคือ:

git reset --hard HEAD~5

สิ่งนี้จะพาคุณย้อนกลับไปห้าข้อผูกพันแล้วด้วย

git pull

ฉันพบว่าโดยดูได้วิธีการที่จะยกเลิกการผสาน Git


นี่คือสิ่งที่ทำงานในท้ายที่สุดสำหรับฉันเป็นฉันมีแรงผลักดันให้สาขาของฉันที่จะซื้อคืนต้นกำเนิดและเก็บไว้ได้รับความขัดแย้งผสานเมื่อพยายามที่จะดึงมันจะ repo ระยะไกลของฉัน ..
jwfrench

สวัสดีจริง ๆ นี่เป็นเคล็ดลับสำหรับwork aroundแต่มีประสิทธิภาพจริงๆ เนื่องจากความขัดแย้งบางอย่างอาจเกิดขึ้นเพียงไม่กี่คอมมิตจากนั้นการคืนค่า 5 คอมมิทจะทำให้แน่ใจว่าไม่มีข้อขัดแย้งกับรหัสระยะไกล
Hoang Le

54

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

นี่คือทางออกที่สะอาดที่สุดที่เราใช้อยู่:

# Fetch the newest code
git fetch

# Delete all files which are being added, so there
# are no conflicts with untracked files
for file in `git diff HEAD..origin/master --name-status | awk '/^A/ {print $2}'`
do
    rm -f -- "$file"
done

# Checkout all files which were locally modified
for file in `git diff --name-status | awk '/^[CDMRTUX]/ {print $2}'`
do
    git checkout -- "$file"
done

# Finally pull all the changes
# (you could merge as well e.g. 'merge origin/master')
git pull
  • คำสั่งแรกดึงข้อมูลใหม่ล่าสุด

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

  • คำสั่งที่สามเช็กเอาต์ไฟล์ทั้งหมดที่ถูกแก้ไขแบบโลคัล

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


การใช้ "git merge origin / master" เป็นบรรทัดสุดท้าย (เช่นที่คุณพูดในบันทึกย่อ) แทน "git pull" จะเร็วขึ้นเมื่อคุณดึงการเปลี่ยนแปลงใด ๆ จาก repo git
Josh

1
ใช่แน่นอนgit merge origin/masterจะเร็วขึ้นและอาจปลอดภัยกว่า เนื่องจากหากมีคนผลักดันการเปลี่ยนแปลงใหม่ในระหว่างการลบไฟล์ของสคริปต์นี้ (ซึ่งไม่น่าจะเกิดขึ้น แต่เป็นไปได้) การดึงทั้งหมดอาจล้มเหลว เหตุผลเดียวที่ฉันใส่pullเพราะมีบางคนอาจไม่ได้ทำงานในสาขาหลัก แต่สาขาอื่น ๆ และฉันต้องการให้สคริปต์เป็นสากล
Strahinja Kustudic

.gitignoreหากคุณได้สร้างไว้ในเครื่องไฟล์เช่นไฟล์ตัวเลือกที่ใส่ไว้ใน
Sebi

52

ก่อนอื่นให้ลองวิธีมาตรฐาน:

git reset HEAD --hard # To remove all not committed changes!
git clean -fd         # To remove all untracked (non-git) files and folders!

คำเตือน : คำสั่งข้างต้นอาจส่งผลให้ข้อมูล / ไฟล์สูญหายได้หากคุณไม่ได้กำหนดไว้! หากคุณไม่แน่ใจให้ทำการสำรองข้อมูลก่อนจากโฟลเดอร์ที่เก็บข้อมูลทั้งหมดของคุณ

จากนั้นดึงอีกครั้ง

หากข้างต้นจะไม่ช่วยและคุณไม่สนใจเกี่ยวกับไฟล์ / ไดเรกทอรีที่ไม่ได้ติดตาม (ทำการสำรองข้อมูลเป็นกรณีแรก) ให้ลองทำตามขั้นตอนง่าย ๆ ดังต่อไปนี้:

cd your_git_repo  # where 'your_git_repo' is your git repository folder
rm -rfv *         # WARNING: only run inside your git repository!
git pull          # pull the sources again

การดำเนินการนี้จะลบไฟล์ git ทั้งหมด (excempt .git/dir ที่คุณมีคอมมิททั้งหมด) แล้วดึงอีกครั้ง


เหตุใดจึงgit reset HEAD --hardล้มเหลวในบางกรณี

  1. กฎที่กำหนดเองใน .gitattributes file

    การมีeol=lfกฎใน. gitattributes อาจทำให้ git แก้ไขไฟล์บางไฟล์ได้โดยแปลง CRLF line-endings เป็น LF ในไฟล์ข้อความบางไฟล์

    หากเป็นเช่นนั้นคุณต้องยอมรับการเปลี่ยนแปลง CRLF / LF เหล่านี้ (โดยตรวจสอบในgit status) หรือลอง: git config core.autcrlf falseเพื่อเพิกเฉยต่อการเปลี่ยนแปลงเหล่านั้นชั่วคราว

  2. ความไม่สมบูรณ์ของระบบไฟล์

    เมื่อคุณใช้ระบบไฟล์ซึ่งไม่รองรับคุณสมบัติการอนุญาต ในตัวอย่างคุณมีสองที่เก็บหนึ่งแห่งบน Linux / Mac ( ext3/ hfs+) และอีกแห่งหนึ่งบน FAT32 / NTFS ระบบไฟล์

    ตามที่คุณสังเกตเห็นว่ามีระบบไฟล์สองประเภทที่แตกต่างกันดังนั้นระบบที่ไม่รองรับการอนุญาต Unix โดยทั่วไปจะไม่สามารถรีเซ็ตการอนุญาตไฟล์ในระบบที่ไม่รองรับการอนุญาตประเภทนั้นได้ดังนั้นไม่ว่า--hardคุณจะพยายามอย่างไร ตรวจสอบ "การเปลี่ยนแปลง" บางอย่างเสมอ


47

ผมมีปัญหาเดียวกัน. ไม่มีใครแก้ปัญหานี้ให้ฉันได้ แต่มันได้ผลกับฉัน

ฉันแก้ไขมันโดย:

  1. ลบไฟล์ทั้งหมด ทิ้งไว้เพียง.gitไดเรกทอรี
  2. git reset --hard HEAD
  3. git pull
  4. git push

ตอนนี้มันใช้งานได้


1
กันที่นี่ บางครั้งการแก้ปัญหาที่ยากมากเท่านั้นมันเกิดขึ้นบ่อยครั้งที่การรีเซ็ตและทำความสะอาดนั้นไม่เพียงพอ ...
jdehaan

41

โบนัส:

เมื่อพูดถึงการดึง / ดึง / รวมในคำตอบก่อนหน้านี้ฉันต้องการแบ่งปันเคล็ดลับที่น่าสนใจและมีประสิทธิผล

git pull --rebase

คำสั่งข้างต้นนี้เป็นคำสั่งที่มีประโยชน์ที่สุดในชีวิต Git ของฉันซึ่งช่วยประหยัดเวลาได้มาก

ก่อนที่จะส่งการคอมมิตไปยังเซิร์ฟเวอร์ลองคำสั่งนี้และมันจะซิงโครไนซ์การเปลี่ยนแปลงเซิร์ฟเวอร์ล่าสุดโดยอัตโนมัติ (ด้วยการดึงข้อมูล + ผสาน) และจะทำการคอมมิทของคุณที่ด้านบนในบันทึก Git ไม่จำเป็นต้องกังวลเกี่ยวกับการดึง / รวมด้วยตนเอง

ค้นหารายละเอียดใน"git pull --rebase" ทำอะไรได้บ้าง .


3
ในระยะสั้น: git pull -r.
kenorb

29

ฉันมีปัญหาที่คล้ายกัน ฉันต้องทำสิ่งนี้:

git reset --hard HEAD
git clean -f
git pull

6
ใช้git cleanด้วยความระมัดระวัง
nategood

29

ฉันสรุปคำตอบอื่น ๆ คุณสามารถดำเนินการได้git pullโดยไม่มีข้อผิดพลาด:

git fetch --all
git reset --hard origin/master
git reset --hard HEAD
git clean -f -d
git pull

คำเตือน : สคริปต์นี้มีประสิทธิภาพมากดังนั้นคุณอาจสูญเสียการเปลี่ยนแปลง


2
สิ่งนี้จะเขียนทับไฟล์ที่ถูกแก้ไข (ไฟล์ที่เคยเช็คอินก่อนหน้า) และจะลบไฟล์ที่ไม่ได้ติดตาม (ไฟล์ที่ไม่เคยเช็คอิน) ว่าสิ่งที่ฉันกำลังมองหาขอบคุณ!
styfle

3
ฉันสงสัยว่าบรรทัดที่สามgit reset --hard HEADอาจซ้ำซ้อน หน้า man ท้องถิ่นของฉัน (2.6.3) บอกว่าresetในบรรทัดที่สองgit reset --hard origin/master "ค่าเริ่มต้นไปที่ HEAD ในทุกรูปแบบ"
arichards

2
@ arichards ฉันคิดว่าผู้ต้องสงสัยของคุณถูกต้อง แต่ถ้าบรรทัดที่สองจะไม่ทำงาน (ไม่ว่าด้วยเหตุผลใดก็ตาม) บรรทัดที่สามจะทำงานได้ดีในการรีเซ็ต โซลูชันนี้ไม่จำเป็นต้องปรับให้เหมาะสม ฉันเพิ่งสรุปคำตอบอื่น ๆ นั่นคือทั้งหมดที่ ขอบคุณสำหรับความคิดเห็นของคุณ. :)
Robert Moon

28

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

ฉันได้อัปเดตสคริปต์ของ Kustudic เพื่อทำสิ่งนั้น ฉันยังคงพิมพ์ผิด (ที่หายไป 'ในต้นฉบับ)

#/bin/sh

# Fetch the newest code
git fetch

# Delete all files which are being added,
# so there are no conflicts with untracked files
for file in `git diff HEAD..origin/master --name-status | awk '/^A/ {print $2}'`
do
    echo "Deleting untracked file $file..."
    rm -vf "$file"
done

# Checkout all files which have been locally modified
for file in `git diff HEAD..origin/master --name-status | awk '/^M/ {print $2}'`
do
    echo "Checking out modified file $file..."
    git checkout $file
done

# Finally merge all the changes (you could use merge here as well)
git pull

การใช้ "git merge origin / master" เป็นบรรทัดสุดท้าย (เช่นที่คุณพูดในบันทึกย่อ) แทน "git pull" จะเร็วขึ้นเมื่อคุณดึงการเปลี่ยนแปลงใด ๆ จาก repo git
Josh

จำเป็นต้องเช็กเอาต์ไฟล์ที่แก้ไขเพื่อให้สามารถใช้งานได้ 100% ฉันอัปเดตสคริปต์ของฉันเมื่อนานมาแล้ว แต่ลืมอัปเดตที่นี่เช่นกัน ฉันยังใช้มันแตกต่างจากคุณเล็กน้อย ฉันเช็กเอาต์ไฟล์ที่มีการดัดแปลงทุกประเภทไม่ใช่แค่ M ดังนั้นมันจึงทำงานได้ตลอดเวลา
Strahinja Kustudic

24

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

  • ไฟล์ในเครื่องที่ไม่ได้ติดตามจะต้องถูกลบไม่ว่าจะด้วยตนเอง (ปลอดภัย) หรือตามคำแนะนำในคำตอบอื่น ๆ ด้วย git clean -f -d

  • การกระทำในท้องถิ่นที่ไม่ได้อยู่ในสาขาระยะไกลจะต้องถูกลบเช่นกัน IMO วิธีที่ง่ายที่สุดในการบรรลุเป้าหมายคือ: git reset --hard origin/master(แทนที่ 'master' ด้วยสาขาใดก็ตามที่คุณกำลังทำงานอยู่และเรียกใช้git fetch originก่อน)


22

วิธีที่ง่ายกว่าคือ:

git checkout --theirs /path/to/file.extension
git pull origin master

สิ่งนี้จะแทนที่ไฟล์ในเครื่องของคุณด้วยไฟล์บนคอมไพล์


21

ดูเหมือนว่าคำตอบส่วนใหญ่ที่นี่เน้นไปที่masterสาขา อย่างไรก็ตามมีบางครั้งที่ฉันกำลังทำงานในสาขาคุณลักษณะเดียวกันในสองแห่งที่แตกต่างกันและฉันต้องการสะท้อนให้เห็นในที่หนึ่งโดยไม่ต้องกระโดดข้ามห่วง

ขึ้นอยู่กับการรวมกันของคำตอบที่อาร์เอ็นเอของและคำตอบ torek เพื่อคำถามที่คล้ายกันผมได้มาด้วยนี้ซึ่งทำงานได้อย่างยอดเยี่ยม:

git fetch
git reset --hard @{u}

เรียกใช้จากสาขาและจะรีเซ็ตเฉพาะสาขาของคุณเป็นเวอร์ชันอัปสตรีม

สิ่งนี้สามารถใส่ลงในนามแฝง git ( git forcepull) ได้เป็นอย่างดี:

git config alias.forcepull "!git fetch ; git reset --hard @{u}"

หรือใน.gitconfigไฟล์ของคุณ:

[alias]
  forcepull = "!git fetch ; git reset --hard @{u}"

สนุก!


คำตอบนี้ก็ดีเช่นกันเพราะมันทำงานได้ดีไม่ว่าคุณจะสาขาไหน
leafmeal

19

ฉันมีปัญหาเดียวกันและด้วยเหตุผลบางอย่างแม้แต่git clean -f -dจะไม่ทำ นี่คือเหตุผล: ด้วยเหตุผลบางอย่างถ้าไฟล์ของคุณจะถูกละเลยโดย Git (ผ่านรายการ .gitignore ผมสมมติ) ก็ยังคงรบกวนจิตใจเกี่ยวกับการเขียนทับนี้กับต่อมาดึงแต่สะอาด-xจะไม่ลบมันจนกว่าคุณจะเพิ่ม


19

ฉันรู้วิธีที่ง่ายและเจ็บปวดน้อยกว่ามาก:

$ git branch -m [branch_to_force_pull] tmp
$ git fetch
$ git checkout [branch_to_force_pull]
$ git branch -D tmp

แค่นั้นแหละ!


18

ฉันเพิ่งแก้ไขปัญหานี้ด้วยตัวเองโดย:

git checkout -b tmp # "tmp" or pick a better name for your local changes branch
git add -A
git commit -m 'tmp'
git pull
git checkout master # Or whatever branch you were on originally
git pull
git diff tmp

โดยที่คำสั่งสุดท้ายแสดงรายการการเปลี่ยนแปลงในพื้นที่ของคุณ ทำการปรับเปลี่ยนสาขา "tmp" จนกว่ามันจะเป็นที่ยอมรับแล้วผสานกลับไปยังต้นแบบด้วย:

git checkout master && git merge tmp

ในครั้งต่อไปคุณอาจจัดการกับสิ่งนี้ได้อย่างสะอาดตาโดยค้นหา "git stash branch" แม้ว่า stash จะทำให้คุณเดือดร้อนในการลองครั้งแรกดังนั้นลองทำการทดลองครั้งแรกในโครงการที่ไม่สำคัญ ...


17

ฉันมีสถานการณ์ที่แปลกว่าไม่git cleanหรือgit resetผลงาน ฉันต้องลบไฟล์ที่มีข้อขัดแย้งออกgit indexโดยใช้สคริปต์ต่อไปนี้ในทุกไฟล์ที่ไม่ได้ติดตาม:

git rm [file]

จากนั้นฉันก็สามารถดึงได้



14

แม้จะมีคำถามดั้งเดิมคำตอบที่ดีที่สุดอาจทำให้เกิดปัญหากับผู้ที่มีปัญหาคล้ายกัน แต่ไม่ต้องการสูญเสียไฟล์ในเครื่อง ตัวอย่างเช่นดูความคิดเห็นของ Al-Punk และ crizCraig

รุ่นต่อไปนี้กระทำการเปลี่ยนแปลงในพื้นที่ของคุณเป็นสาขาชั่วคราว ( tmp) ตรวจสอบสาขาเดิม (ซึ่งฉันสมมติว่าเป็นmaster) และผสานการปรับปรุง คุณสามารถทำได้ด้วยstashแต่ฉันพบว่ามันง่ายกว่าที่จะใช้วิธีการสาขา / การผสาน

git checkout -b tmp
git add *; git commit -am "my temporary files"
git checkout master

git fetch origin master
git merge -s recursive -X theirs origin master

ที่เราถือว่าพื้นที่เก็บข้อมูลอื่น ๆorigin masterคือ


13

คำสั่งทั้งสี่นี้ใช้ได้สำหรับฉัน

git reset --hard HEAD
git checkout origin/master
git branch -D master
git checkout -b master

ในการตรวจสอบ / ดึงหลังจากเรียกใช้คำสั่งเหล่านี้

git pull origin master

ฉันพยายามมาก แต่ในที่สุดก็ประสบความสำเร็จกับคำสั่งเหล่านี้


2
"git branch -D master" ลบสาขา ดังนั้นระวังด้วย ฉันชอบที่จะใช้ "ต้นกำเนิดเช็คเอาต์ git / master -b <ชื่อสาขาใหม่>" ซึ่งสร้างสาขาใหม่ที่มีชื่อใหม่และคุณต้องการ 3,4 บรรทัด ยังแนะนำให้ใช้ "git clean -f" เช่นกัน
Chand Priyankara

13

แค่ทำ

git fetch origin branchname
git checkout -f origin/branchname // This will overwrite ONLY new included files
git checkout branchname
git merge origin/branchname

ดังนั้นคุณหลีกเลี่ยงผลข้างเคียงที่ไม่ต้องการทั้งหมดเช่นการลบไฟล์หรือไดเรกทอรีที่คุณต้องการเก็บเป็นต้น


12

รีเซ็ตดัชนีและส่วนหัวเป็นorigin/masterแต่อย่ารีเซ็ตแผนผังการทำงาน:

git reset origin/master

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

12

ที่ต้องการ:

  1. ติดตามการเปลี่ยนแปลงในพื้นที่ดังนั้นจึงไม่มีใครเสียที่นี่เลย
  2. ทำให้ที่เก็บโลคัลตรงกับที่เก็บรีโมตต้นทาง

สารละลาย:

  1. ซ่อนการเปลี่ยนแปลงในเครื่อง
  2. การดึงข้อมูลที่มีความสะอาดของไฟล์และไดเรกทอรีละเว้น.gitignoreและฮาร์ดรีเซ็ตการกำเนิด

    git stash --include-untracked
    git fetch --all
    git clean -fdx
    git reset --hard origin/master
    
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.