git mv และเปลี่ยนเฉพาะกรณีของไดเรกทอรี


259

ในขณะที่ฉันพบคำถามที่คล้ายกันฉันไม่พบคำตอบสำหรับปัญหาของฉัน

เมื่อฉันพยายามเปลี่ยนชื่อไดเรกทอรีจาก FOO เป็น foo ผ่านgit mv FOO fooฉันจะได้รับ

fatal: renaming 'FOO' failed: Invalid argument

ตกลง. ดังนั้นฉันลองgit mv FOO foo2 && git mv foo2 foo

แต่เมื่อฉันพยายามที่จะกระทำผ่านgit commit .ฉันได้รับ

# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
# foo
nothing added to commit but untracked files present (use "git add" to track)

เมื่อฉันเพิ่มไดเรกทอรีผ่านgit add fooการเปลี่ยนแปลงอะไรและgit commit .ทำให้ฉันข้อความเดียวกันอีกครั้ง

ผมทำอะไรผิดหรือเปล่า? ฉันคิดว่าฉันใช้ระบบเล็กและตัวพิมพ์ใหญ่ (OSX) ทำไมฉันไม่สามารถเปลี่ยนชื่อไดเรกทอรีได้


10
ระบบไฟล์ของ OS X ไม่คำนึงถึงขนาดตัวพิมพ์
mipadi

2
@mipadi มันสามารถทำงานในโหมดตัวพิมพ์เล็กหรือตัวพิมพ์ใหญ่ แต่โดยปกติแล้วจะปิดโดยปริยาย
GordonM

1
คำถาม & คำตอบนี้มีประโยชน์ใน Windows เช่นกัน พิจารณา untagging "OSX"
บาเร็ตต์

1
ดูstackoverflow.com/a/24979063/6309 : ตั้งแต่ git 2.0.1 ซึ่งเป็นgit mvงานง่าย
VonC

บน windows youo สามารถใช้งานปกติgit mv foo Fooหากคุณใช้เปลือก cygwin
Andrew Scott

คำตอบ:


409

คุณอยู่ในสภาพแวดล้อมที่ไม่คำนึงถึงขนาดตัวพิมพ์ นอกจากนี้การเพิ่มโดย-Aไม่ต้องดูแลด้านลบของmvGit ที่เข้าใจ คำเตือน! ตรวจสอบให้แน่ใจว่าไม่มีการเปลี่ยนแปลงอื่น ๆ หรือไฟล์ที่ไม่ได้ติดตามอยู่รอบ ๆ เมื่อคุณทำสิ่งนี้หรือไฟล์เหล่านั้นจะถูกคอมมิทเป็นส่วนหนึ่งของการเปลี่ยนแปลงนี้! git stash -uก่อนอื่นให้ทำและgit stash popหลังจากนั้น ดำเนินการต่อเพื่อรับสิ่งนี้ให้ทำดังต่อไปนี้:

mv foo foo2
git add -A
git commit -m "renaming"
mv foo2 FOO
git add -A
git commit --amend -m "renamed foo to FOO"

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

git mv foo foo2
git mv foo2 FOO
git commit -m "changed case of dir"

ตามที่แนะนำไว้ในความคิดเห็นอย่างใดอย่างหนึ่งคุณยังสามารถทำการรีบูตแบบโต้ตอบได้ ( git rebase -i HEAD~5หากมีการแนะนำกรณีผิด 5 ครั้งที่แล้ว) เพื่อแก้ไขกรณีที่เกิดขึ้นและไม่มีกรณีผิดปรากฏขึ้นที่ใดก็ได้ในประวัติศาสตร์เลย คุณต้องระวังหากคุณทำเช่นนี้เนื่องจากแฮชการคอมมิชชันต่อจากนั้นจะแตกต่างกันและผู้อื่นจะต้องทำการ rebase หรือรวมงานของพวกเขากับสาขาที่ผ่านมาในอดีต

สิ่งนี้เกี่ยวข้องกับการแก้ไขชื่อไฟล์: git ไม่สนใจขนาดตัวพิมพ์หรือไม่


1
ขอบคุณ นี่ทำให้ฉันบ้า ฉันไม่รู้เกี่ยวกับตัวเลือก - หรือ - แก้ไข
oschrenk

7
โปรดระวังด้วย - เนื่องจากจะเพิ่มเนื้อหาทั้งหมดซ้ำในไดเรกทอรีปัจจุบันของคุณรวมถึงเนื้อหาที่ไม่ได้ติดตาม git add foo2อาจจะดีกว่าที่จะเพียงแค่
rich.e

2
ถูกต้อง. อย่างไรก็ตามคุณจะต้องทำการกำจัดทั้ง foo2 และ FOO แยกต่างหาก -Aดูแลทั้งสองอย่าง ในทางกลับกันสำหรับขั้นตอนแรก ฉันจะเพิ่มคำเตือน ขอบคุณ!
Adam Dymitruk

นอกจากนี้คุณยังสามารถทำความสะอาดประวัติของคุณกับ git rebase -i HEAD~2rebase หมายเหตุ: หากต้องการทำให้สิ่งนี้ง่ายขึ้นให้ตั้งค่าข้อความสุดท้ายในการส่งครั้งแรกและแก้ไขข้อความที่สอง
Alex B.

5
ฉันประสบความสำเร็จกับ git mv foo foo2; git mv foo2 FOO; คอมไพล์กระทำ
Chris

146

คุณต้องการตั้งค่าตัวเลือกcore.ignorecaseเป็นเท็จซึ่งจะทำให้ Git ให้ความสนใจกับตัวพิมพ์เล็กและใหญ่ในระบบไฟล์ที่ไม่สนับสนุน วิธีเปิดใช้งานใน repo ของคุณ:

$ git config core.ignorecase false

จากนั้นคุณสามารถเปลี่ยนชื่อไฟล์ด้วยgit mvและมันจะทำงานตามที่คาดไว้


1
ฉันคิดว่านี่อาจมีผลกระทบที่ไม่พึงประสงค์ที่อื่น ระบบที่ไม่คำนึงถึงขนาดตัวพิมพ์ควรให้ Git คิดว่ามันเป็น dir ตัวเดียวกัน
Adam Dymitruk

2
ฉันจะเพิ่มตัวเลือกในการตั้งค่าระดับโลกของฉัน แต่มันไม่ได้ช่วย
oschrenk

3
ฉันเห็นพฤติกรรมแปลก ๆ บางอย่างเมื่อใช้กับ OSX hrm I modified a file that doesn't exist.. hrm error: The following untracked working tree files would be overwritten by checkout:แต่ ... ไฟล์เหล่านั้นไม่มีอยู่
Skylar Saveland

นี่คือสิ่งที่ฉันกำลังมองหา ฉันใช้ CentOS 5.6 และไม่ได้รับการเปลี่ยนแปลงของคดี
crmpicco

5
มันใช้งานไม่ได้! ใน Git 1.8.3 Git จะถือว่าไฟล์ที่ถูกเปลี่ยนชื่อเป็นไฟล์ใหม่แทนที่จะลบ + เพิ่ม การกระทำดังกล่าวจะทำให้ที่เก็บมีไฟล์เดียวกันสองไฟล์เช่น foo และ FOO มีอยู่ทั้งสอง! แต่เมื่อเช็คเอาต์ปรากฏเพียงไฟล์เดียว (แต่กรณีหนึ่งอาจครอบงำมากกว่าอีกกรณี)
Johnny Wong

68

ฉันสามารถแก้ไขได้โดยใช้ git 1.7.7 โดยใช้ชื่อไฟล์ชั่วคราว:

$ git mv improper_Case improve_case2
$ git mv improve_case2 improve_case
$ git commit -m "<your message>"

น่าสนใจ บางที GIT ก็ปรับปรุงบางอย่างตั้งแต่นั้นมา เมื่อฉันจะสะดุดปัญหานี้อีกครั้งฉันจะลองอีกครั้ง
oschrenk

ทำแบบนี้ง่ายกว่ามาก
โอลด์

ทำงานสำหรับฉันใน macOS
Mr_Pouet

14

( git mv- ตัวแปรฟรี)

ฉันพบปัญหานี้ใน Git บน Mac OS X 10.9 ฉันแก้ไขมันดังนี้

git rm -r --cached /path/to/directory

ขั้นตอนนี้จะทำให้ไดเรกทอรีสำหรับการลบใน Git แต่ไม่ได้ลบไฟล์ทางกายภาพใด ๆ ( --cached) นอกจากนี้ยังทำให้ไดเรกทอรีตอนนี้มีกรณีที่เหมาะสมแสดงในไฟล์ที่ไม่ได้ติดตาม

ดังนั้นคุณสามารถทำสิ่งนี้:

mv /path/to/directory /path/to/DIRECTORY
git add -A /path/to/DIRECTORY

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


ฉันพบว่าmvคำสั่งไม่ทำงานเพื่อเปลี่ยนชื่อไดเรกทอรีจริง ฉันต้องเปลี่ยนชื่อภายใน Finder นอกเหนือจากนั้นการแก้ไขนี้ทำงานได้อย่างสมบูรณ์แบบ
Adam S

9

นี่เป็นวิธีแก้ปัญหาที่รวดเร็วและปลอดภัย:

git mv -f path/to/foo/* path/to/FOO/

คำเตือน! เปลี่ยนชื่อไฟล์ทั้งหมดในโฟลเดอร์ที่ถูกเปลี่ยนชื่อ (ใช้/*) เสมอ

อย่าเปลี่ยนชื่อไฟล์เดียว สิ่งนี้นำไปสู่ข้อผิดพลาดที่อธิบายไว้ในคำตอบนี้

หากคุณต้องการเห็นผลลัพธ์ก่อนอื่นให้ใช้-n:

git mv -f -n path/to/foo/* path/to/FOO/

หลังจากที่คุณทำmv:

  1. กระทำการเปลี่ยนแปลง
  2. ชำระเงินให้กับการแก้ไขอื่น ๆ
  3. ชำระเงินคืน

ตอนนี้ Git ควรเปลี่ยนชื่อโฟลเดอร์ทั้งในไฟล์ภายในและในระบบไฟล์


นี่เป็นเพียงสำหรับ Git 2.0.1 ตามที่ฉันพูดถึงในความคิดเห็นของคำถามข้างต้นหรือไม่ (หมายถึงstackoverflow.com/a/24979063/6309 )
VonC

8

บังคับด้วยตัวเลือก -f:

git mv -f FOO foo

ไม่ได้ผลสำหรับฉัน การตั้งค่าของฉันคือ. git / config "ignorecase = true" การเปลี่ยนชื่อไม่สามารถจัดฉากในพื้นที่การจัดแสดงด้วยวิธีนี้ (เวอร์ชั่น Git 1.8.3.msysgit.0) โซลูชั่นของ Adam Dymitruk เป็นคำตอบเดียวที่ถูกต้อง
Johnny Wong

@JohnnyWong เปลี่ยนการตั้งค่าของคุณเป็นfalseมันใช้ได้สำหรับฉัน
Inder Kumar Rathore

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

@Bryce ไม่คุณจะต้องยอมรับการเปลี่ยนแปลงและผลักดันพวกเขาไปที่ repo ส่วนกลางก่อนที่ผู้ใช้รายอื่นจะสามารถดึงการเปลี่ยนแปลงได้
konyak

3

ฉันมีปัญหาหนึ่งที่เกี่ยวข้อง

หนึ่งโฟลเดอร์ชื่อ 'Pro' (สร้างขึ้นก่อน) และอีกโฟลเดอร์หนึ่ง 'โปร' (สร้างโดยไม่ได้ตั้งใจ) ใน Mac มันเหมือนกัน แต่แตกต่างกันตามคอมไพล์

$ git config core.ignorecase false

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

แทนที่จะเป็นเช่นนั้นฉันก็ทำ

$ git rm -r --cached pro
$ git status // => pro files removed, new Pro files untracked
$ git add Pro

เพื่อให้ปลอดภัยเป็นพิเศษฉันทำมันในสาขาการแก้ไขที่แยกต่างหากจากนั้นฉันก็รวมกลับไปที่สาขาหลัก

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


2

คุณไม่ได้ใช้ระบบไฟล์แบบตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ใน OS X เว้นแต่คุณจะเลือกอย่างชัดเจน HFS + สามารถเป็นแบบตรงตามตัวพิมพ์ใหญ่ - เล็ก แต่ค่าเริ่มต้นนั้นไม่ตรงตามตัวพิมพ์ใหญ่ - เล็ก


4
การใช้ระบบไฟล์แบบตรงตามตัวพิมพ์ใหญ่ - เล็กบน OS X ไม่ใช่ความคิดที่ดี แอพจำนวนมากทำงานไม่ถูกต้องฉันเรียนรู้จากการลองสิ่งนี้ ปัญหาอย่างหนึ่งคือ Adobe Photoshop จะปฏิเสธที่จะติดตั้งโดยบอกว่าระบบไฟล์นั้นไม่ได้รับการรองรับ
jpswain

1

นี่เป็นวิธีแก้ปัญหาที่ง่ายมาก ๆ สำหรับ gitfoo ทั้งหมดในหน้านี้

  1. คัดลอกไฟล์จากโครงการของคุณด้วยตนเอง
  2. git rm ไฟล์ทั้งหมด
  3. คอมไพล์กระทำเช่นปกติ
  4. เพิ่มไฟล์กลับด้วยตนเอง
  5. git เพิ่มไฟล์ทั้งหมด
  6. คอมไพล์กระทำเช่นปกติ
  7. กำไร.

1
มันใช้งานได้ในพื้นที่ แต่ถ้ามีคนอื่นดึงมันจะไม่เปลี่ยนกรณีของพวกเขา
Jason

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

0

การปรับปรุงคำตอบของ Adam Dymitruk (งี่เง่าที่ SO ไม่ให้ความเห็นคำตอบของเขา) การใช้ "git mv" จะแสดงไฟล์ที่ถูกย้ายโดยอัตโนมัติ ไม่จำเป็นต้องมีการ stashing และ "git add -A" ที่มีความเสี่ยงสามารถหลีกเลี่ยงได้:

old="abc";    new="ABC";
tmp="$old-renamed";
git mv "$old" "$tmp";
git commit -m "Renamed '$old' to '$tmp'.";
git mv "$tmp" "$new";
git commit --amend -m "Renamed '$old' to '$new'.";

0

มันใช้งานได้ดีสำหรับฉันบน Windows PowerShell ที่ใช้มีดังต่อไปนี้:

  1. mv .\Folder-With-Wrong-Casing .\temp
  2. git add -A
  3. git commit -m "renamed folder with wrong casing to temp"
  4. mv .\temp .\Folder-with-Correct-Casing
  5. git add -A
  6. git commit --amend -m "Renamed to proper casing"
  7. (ไม่จำเป็น) git push

ขอบคุณคำตอบของอดัมด้านบน

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