Git: จะเปลี่ยนไฟล์ 2 ไฟล์ที่ติดค้างอยู่ที่ "เปลี่ยนแปลง แต่ไม่ได้รับการยืนยัน" ได้อย่างไร?


84

ฉันมี repo ที่มีสองไฟล์ที่ฉันควรเปลี่ยนในเครื่อง

ฉันติดอยู่กับสิ่งนี้:

$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   dir1/foo.aspx
#       modified:   dir2/foo.aspx
#
no changes added to commit (use "git add" and/or "git commit -a")

การทำgit diffบอกว่าเนื้อหาของไฟล์ทั้งหมดมีการเปลี่ยนแปลงแม้ว่าจะดูไม่เป็นความจริง (ดูเหมือนจะมีช่วงบรรทัดทั่วไปที่ดูเหมือนว่าจะไม่สามารถมองเห็นได้)

ที่น่าสนใจคือฉันจำไม่ได้ว่าเปลี่ยนไฟล์เหล่านี้ในเครื่อง repo นี้ใช้กับ repo ระยะไกลหนึ่งรายการ (ส่วนตัวที่ GitHub.com, FWIW)

ไม่ว่าฉันจะพยายามอย่างไรฉันก็ไม่สามารถละทิ้งการเปลี่ยนแปลงเหล่านี้ได้ ฉันได้ลองทั้งหมด:

$ git checkout -- .
$ git checkout -f
$ git checkout -- dir1/checkout_receipt.aspx
$ git reset --hard HEAD
$ git stash save --keep-index && git stash drop
$ git checkout-index -a -f

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

ห่าอะไรจะทำให้สองไฟล์ติดแบบนี้และดูเหมือนจะ "ยกเลิกการเปลี่ยนตาราง" ??

PS ในรายการดังกล่าวข้างต้นแสดงให้เห็นคำสั่งที่ฉันพยายามแล้วผมเข้าใจผิดเขียนเมื่อฉันหมายถึงgit revert ฉันขอโทษและขอบคุณบรรดาผู้ที่ตอบว่าผมควรจะลองgit checkout checkoutฉันแก้ไขคำถามเพื่อแก้ไข checkoutแน่นอนผมลองแล้ว


ไม่git diff --ignore-space-changeหรือgit diff --ignore-all-spaceสร้างความแตกต่างในการส่งออกของที่git diff?
jdd

@jermiahd ใช่! ด้วยแฟล็กอย่างใดอย่างหนึ่งgit diffระบุว่าไฟล์เหมือนกัน
Greg Hendershott

2
ซ้ำเป็นไปได้ของstackoverflow.com/questions/2016404/... ฉันชอบคำตอบที่ได้รับการยอมรับมากกว่าอยู่ดีซึ่งก็คือการตั้งค่าgit config --global core.autocrlf falseแทน 'จริง'
Johann

2
คำตอบ [ที่นี่] [1] ใช้ได้ผลกับฉันและคนอื่น ๆ อีกมากมาย [1]: stackoverflow.com/questions/2016404/…
Mike K

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

คำตอบ:


34

ส่วนท้ายบรรทัดในไฟล์คืออะไร? ฉันพนันว่าพวกเขาเป็น CRLF หากเป็นเช่นนั้นโปรดดูคู่มือนี้: http://help.github.com/line-endings/

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


1
ขอบคุณ. ฉันมีอยู่แล้วgit config --global core.autocrlf trueอีกฝ่ายก็ดันไปที่ repo บน GitHub
Greg Hendershott

1
จากนั้นคุณควรทำบิตใน<pre>บล็อกสุดท้ายของคำแนะนำนั้นเพื่อแก้ไขไฟล์ใน repo
Tekkub

5
ฉันไม่เห็นด้วยที่การลงท้ายบรรทัดควรเป็น LF ใน repo เสมอ (โดยเฉพาะอย่างยิ่งถ้ามีคนอื่นยอมรับ CRLF แล้ว) และระบบปฏิบัติการควรเป็นแบบเนทีฟเสมอ ตัวแก้ไขและสภาพแวดล้อม Windows ของฉัน (ส่วนใหญ่ใช้กับ PHP, HTML, CSS เป็นต้น) ทำงานได้ดีกับการลงท้ายบรรทัด LF
Simon East

คำตอบอัจฉริยะฉันลืมไปว่าเมื่อเร็ว ๆ นี้ฉันใช้ gitattributes เพื่อบังคับ LF ในไฟล์ repo และไม่ได้คาดหวังว่า git จะเปลี่ยนไฟล์โดยอัตโนมัติ เรามีนักพัฒนา Windows และ Linux ผสมผสานกันและมันทำให้เราคลั่งไคล้ในฐานะบรรณาธิการบนแพลตฟอร์มต่าง ๆ ยังคงเปลี่ยนไลน์เทอร์มิเนเตอร์ออกไปเมื่อการเปลี่ยนแปลงได้กระเพื่อมผ่านทั้งหมดนี้ควรจะหายไป
Oliver Dungey

121

ฉันใช้เวลาหลายชั่วโมงในการพยายามแก้ไขปัญหาที่คล้ายกันซึ่งเป็นสาขาระยะไกลที่ฉันได้ตรวจสอบแล้วซึ่งแสดงให้เห็นว่าไฟล์สี่ไฟล์เป็น 'เปลี่ยนแปลง แต่ไม่อัปเดต' โดยดื้อรั้นแม้ว่าจะลบไฟล์ทั้งหมดและเรียกใช้git checkout -fอีกครั้ง (หรือรูปแบบอื่น ๆ จากโพสต์นี้)!

ไฟล์ทั้งสี่นี้จำเป็น แต่ฉันไม่ได้แก้ไขอย่างแน่นอน ทางออกสุดท้ายของฉัน - ชักชวน Git ว่าพวกเขาไม่ได้รับการเปลี่ยนแปลง ต่อไปนี้ใช้ได้กับไฟล์ที่เช็คเอาต์ทั้งหมดโดยแสดงสถานะ 'แก้ไข' - ตรวจสอบให้แน่ใจว่าคุณได้ยืนยัน / ซ่อนข้อมูลใด ๆ ที่ได้รับการแก้ไขแล้ว!:

git ls-files -m | xargs -i git update-index --assume-unchanged "{}"

บน Mac OSX อย่างไรก็ตาม xargs ทำงานแตกต่างกันเล็กน้อย (ขอบคุณ Daniel สำหรับความคิดเห็น):

git ls-files -m | xargs -I {} git update-index --assume-unchanged {}

ฉันได้เพิ่มสิ่งนี้เป็นตัวยึดสำหรับตัวเองในครั้งต่อไป แต่ฉันหวังว่ามันจะช่วยคนอื่นด้วย

- อัล


10
ฉันมีไฟล์ที่ดื้อรั้นสองสามไฟล์และเรียกใช้คำสั่งนี้สถานะ git ตอนนี้ไม่มีการเปลี่ยนแปลง แต่เมื่อฉันพยายามเปลี่ยน branch git ก็ยังบอกฉันว่าฉันไม่สามารถเปลี่ยน branch ได้เพราะทั้งสองไฟล์มีการเปลี่ยนแปลงในเครื่อง ไม่แน่ใจว่าฉันทำอะไรผิดไป แต่ดูเหมือนว่ามันจะครอบคลุมปัญหามากกว่าการแก้ไข? ฉันไม่สามารถคอมมิตไฟล์หลังจากเรียกใช้คำสั่งนั้น วิธีแก้ปัญหาสำหรับฉันคือการลบพวกเขากระทำและแลกเปลี่ยนสาขา
RodH257

5
ขอบคุณ! ฉันลองใช้กลเม็ดทั้งหมดที่กล่าวถึงในทุกคำตอบที่ฉันพบ - ไม่มีอะไรได้ผล บน mac ไม่สามารถใช้บรรทัดได้ตามที่เป็นอยู่เพียงแค่เรียกใช้ git update-index - สมมติว่าไม่มีการเปลี่ยนแปลง <filename> ในแต่ละไฟล์และทำให้ปัญหานี้หายไป
Yonatan Karni

6
นี่คือสิ่งที่ฉันต้องการแม้ว่า xargs บน mac ดูเหมือนจะทำงานแตกต่างกันเล็กน้อย (ฉันใช้ 10.10 Yosemite) ในที่สุดสิ่งนี้ก็ได้ผลสำหรับฉัน:git ls-files -m | xargs -I {} git update-index --assume-unchanged {}
Daniel

4
ในการเปลี่ยนเอฟเฟกต์ของคำสั่ง:git ls-files -v|grep '^h' | cut -c3- | xargs -i git update-index --no-assume-unchanged "{}"
Marinos An

3
วิธีนี้ไม่สามารถแก้ไขปัญหาได้ มันซ่อนมันไว้ มีสองสิ่งที่ไม่สามารถทำได้หลังจากassume-unchagedนั้นเช่นในกรณีของ @ RodH257 ผมเชื่อว่าคำตอบที่ถูกต้องที่สุดสำหรับกรณีที่คำสั่งที่ชอบgit checkout -- file, git stashและgit reset --hard HEADไม่ได้ทำงานจะเป็นคำตอบอยู่แล้วการแก้ไข.gitattributes
Marinos

20

นี่คือวิธีที่ฉันแก้ไขปัญหาเดียวกันในกรณีของฉัน: เปิด. gitattributes เปลี่ยน:

* text=auto

ถึง:

#* text=auto

บันทึกและปิดจากนั้นเปลี่ยนกลับหรือรีเซ็ตขอบคุณ @Simon East สำหรับคำใบ้


1
การลบการtext=autoตั้งค่าใน. gitattributes ใช้งานได้สำหรับฉันแล้วหลังจากที่ฉันgit reset --hardนำการตั้งค่านั้นกลับมาไฟล์จะไม่แสดงว่าถูกแก้ไขอีกต่อไป!
ErikE

1
เห็นได้ชัดว่ามีบางอย่างผิดปกติกับtext=autoการตั้งค่านี้ ฉันกำลังทำงานใน repos ที่มีคอมมิตจากหลายระบบปฏิบัติการและฉันยังไม่พบว่าอะไรทำให้ฉันมีปัญหามากขึ้น: จะเก็บมันไว้หรือจะปล่อยมัน
Marinos An

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

12

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

git diff dir1 / foo.aspx

และจะแสดงการเปลี่ยนแปลงโหมดไฟล์ แม้ว่าจะยังไม่ยอมให้คุณเปลี่ยนกลับ สำหรับการใช้งานนั้น

git config core.filemode false

หรือเปลี่ยน git .config ในโปรแกรมแก้ไขข้อความของคุณโดยการเพิ่ม

[หลัก]

filemode = false

หลังจากดำเนินการแล้วคุณสามารถใช้ไฟล์

git รีเซ็ต HEAD dir1 / foo.aspx

และไฟล์ควรจะหายไป

(ฉันได้รับทั้งหมดนี้จากคำตอบฉันจะทำการเปลี่ยนแปลงโหมดละเว้น git ได้อย่างไร (chmod)? )


1
หากคุณใช้ Windows การวินิจฉัย / วิธีแก้ปัญหาของ Eyal ควรเป็นการเดาครั้งแรกของคุณ
AlcubierreDrive

ระวังเป็นพิเศษอย่าใช้ cygwin git จาก cmd.exe หากคุณต้องการ git ใน cmd.exe ให้ติดตั้ง msysgit
AlcubierreDrive

เพียงเพื่อยืนยันว่านี่เป็นปัญหาใน Windows
Dejan Marjanović

สำหรับฉันใน Windows นี่ไม่ใช่ปัญหา ( core.filemodeตั้งค่าเป็นเท็จแล้ว) ในกรณีของการแก้ไข / การแก้ปัญหาเป็นหนึ่งในคำตอบที่อลัน Forsyth ของ
Venryx

3

ลองเปลี่ยนกลับการเปลี่ยนแปลงในเครื่อง :

git checkout -- dir1/foo.aspx
git checkout -- dir2/foo.aspx

ฉันมี "ย้อนกลับ" checkoutในสมองและผมหมายถึงการเขียน checkoutฉันไม่อยู่แล้วลอง ขอบคุณสำหรับคำตอบของคุณ มันเป็นคำตอบที่ดีสำหรับคำถามเดิมของฉันดังนั้นฉันจะโหวตให้คะแนน
Greg Hendershott

3

ฉันมีไฟล์ที่มีการเปลี่ยนแปลง phantom ซึ่งแสดงว่าถูกแก้ไข แต่จริงๆแล้วเหมือนกัน

บางครั้งการเรียกใช้คำสั่งนี้ใช้งานได้:
(ปิดการแปลง "สมาร์ท" ของ git แต่มักจะไม่เป็นประโยชน์)

git config --local core.autocrlf false

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


การลบการtext=autoตั้งค่าใน. gitattributes ใช้งานได้สำหรับฉันแล้วหลังจากที่ฉันgit reset --hardนำการตั้งค่านั้นกลับมาไฟล์จะไม่แสดงว่าถูกแก้ไขอีกต่อไป!
ErikE

2
git checkout dir1/foo.aspx
git checkout dir2/foo.aspx

ฉันมี "ย้อนกลับ" checkoutในสมองและผมหมายถึงการเขียน checkoutฉันไม่อยู่แล้วลอง ขอบคุณสำหรับคำตอบของคุณ มันเป็นคำตอบที่ดีสำหรับคำถามเดิมของฉันดังนั้นฉันจะโหวตให้คะแนน
Greg Hendershott

2

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

หากต้องการตรวจสอบว่าเป็นเช่นนั้นหรือไม่เพียงดูว่าที่เก็บระยะไกลมีโครงสร้างสองชั้นหรือไม่

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


2

ฉันคิดว่าการให้คำแนะนำในการทำให้เกิดปัญหาซ้ำจะเป็นประโยชน์เพื่อให้เข้าใจปัญหาได้ดีขึ้น:

$ git init
$ echo "*.txt -text" > .gitattributes
$ echo -e "hello\r\nworld" > 1.txt
$ git add 1.txt 
$ git commit -m "committed as binary"
$ echo "*.txt text" > .gitattributes
$ echo "change.." >> 1.txt

# Ok let's revert now

$ git checkout -- 1.txt
$ git status
 modified:   1.txt

# Oooops, it didn't revert!!


# hm let's diff:

$ git diff
 warning: CRLF will be replaced by LF in 1.txt.
 The file will have its original line endings in your working 
 directory.
 diff --git a/1.txt b/1.txt
 index c78c505..94954ab 100644
 --- a/1.txt
 +++ b/1.txt
 @@ -1,2 +1,2 @@
 -hello
 +hello
  world

# No actual changes. Ahh, let's change the line endings...

$ file 1.txt 
 1.txt: ASCII text, with CRLF line terminators
$ dos2unix 1.txt
 dos2unix: converting file 1.txt to Unix format ...
$ git diff
 git diff 1.txt
 diff --git a/1.txt b/1.txt
 index c78c505..94954ab 100644
 --- a/1.txt
 +++ b/1.txt
 @@ -1,2 +1,2 @@
 -hello
 +hello
  world

# No, it didn't work, file is still considered modified.

# Let's try to revert for once more:
$ git checkout -- 1.txt
$ git status
 modified:   1.txt

# Nothing. Let's use a magic command that prints wrongly committed files.

$ git grep -I --files-with-matches --perl-regexp '\r' HEAD

HEAD:1.txt

วิธีที่ 2 ในการสร้างซ้ำ: ในสคริปต์ด้านบนให้แทนที่บรรทัดนี้:
echo "*.txt -text" > .gitattributes
ด้วย
git config core.autocrlf=false
และเก็บส่วนที่เหลือของบรรทัดตามที่เป็นอยู่


สิ่งที่กล่าวมาทั้งหมด? ไฟล์ข้อความสามารถ (ในบางสถานการณ์) ถูกผูกมัดกับ CRLF (เช่น-textใน.gitattributes/ หรือcore.autocrlf=false)

เมื่อเราต้องการจัดการไฟล์เดียวกันกับข้อความในภายหลัง ( -text-> text) จะต้องมีการยืนยันอีกครั้ง
แน่นอนคุณสามารถเปลี่ยนกลับได้ชั่วคราว (ตามที่ตอบถูกโดย Abu Assar ) ในกรณีของเรา:

echo "*.txt -text" > .gitattributes
git checkout -- 1.txt
echo "*.txt text" > .gitattributes

คำตอบคือคุณต้องการทำเช่นนั้นจริง ๆ หรือไม่เพราะมันจะทำให้เกิดปัญหาเดียวกันทุกครั้งที่คุณเปลี่ยนไฟล์


สำหรับบันทึก:

หากต้องการตรวจสอบว่าไฟล์ใดที่ทำให้เกิดปัญหานี้ใน repo ของคุณให้ดำเนินการคำสั่งต่อไปนี้ (ควรคอมไพล์ git ด้วย --with-libpcre):

git grep -I --files-with-matches --perl-regexp '\r' HEAD

โดยการส่งไฟล์ (สมมติว่าคุณต้องการให้ถือว่าเป็นข้อความ) มันก็เหมือนกับการทำตามที่เสนอไว้ในลิงค์นี้http://help.github.com/line-endings/เพื่อแก้ไขปัญหาดังกล่าว . แต่แทนที่คุณจะลบ.git/indexและดำเนินการresetคุณสามารถเปลี่ยนไฟล์จากนั้นดำเนินการgit checkout -- xyz zyfแล้วจึงคอมมิต


2

ฉันมีปัญหาเดียวกันพร้อมกับสิ่งที่น่าสนใจเพิ่มเติมที่ไฟล์มีการเปลี่ยนแปลงบน windows แต่ไม่ใช่เมื่อดูจาก WSL ไม่มีความยุ่งเหยิงกับการสิ้นสุดบรรทัดการรีเซ็ตและอื่น ๆ ที่สามารถเปลี่ยนแปลงได้

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


ฉันได้แก้ไขปัญหานี้โดยใช้ขั้นตอนต่อไปนี้

1) ลบทุกไฟล์ออกจากดัชนีของ Git

git rm --cached -r .

2) เขียนดัชนี Git ใหม่เพื่อรับส่วนท้ายบรรทัดใหม่ทั้งหมด

git reset --hard

โซลูชันเป็นส่วนหนึ่งของขั้นตอนที่อธิบายไว้ในเว็บไซต์ git https://help.github.com/articles/dealing-with-line-endings/


1

สำหรับฉันปัญหาไม่ได้เกี่ยวกับการสิ้นสุดบรรทัด เกี่ยวกับการเปลี่ยนกรณีในชื่อโฟลเดอร์ (Reset_password -> Reset_Password) โซลูชันนี้ช่วยฉัน: https://stackoverflow.com/a/34919019/1328513


1

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

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

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