फ़ाइल फ़ाइल git में नाम बदल रहा है


440

मैंने पढ़ा है कि जब git में फ़ाइलों का नाम बदल रहा है , तो आपको कोई भी परिवर्तन करना चाहिए, अपना नाम बदलें और फिर अपनी नामांकित फ़ाइल को स्टेज करें। Git किसी नई अनट्रेक्ड फ़ाइल के रूप में देखने के बजाय, सामग्री से फ़ाइल को पहचान लेगा, और परिवर्तन इतिहास को बनाए रखेगा।

हालाँकि, आज रात बस यही करने के लिए मैं वापस लौट आया git mv

> $ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   index.html
#

से Finder में अपना स्टाइलशीट का नाम बदलें iphone.cssकरने के लिएmobile.css

> $ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   index.html
#
# Changed but not updated:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   deleted:    css/iphone.css
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   css/mobile.css

तो अब मुझे लगता है कि मैंने एक सीएसएस फ़ाइल को हटा दिया है, और एक नया जोड़ा है। मैं जो चाहता हूं, वह नाम बदलने की अनुमति न दें और काम करने दें।

> $ git reset HEAD .
Unstaged changes after reset:
M   css/iphone.css
M   index.html

वापस जहां से मैं शुरू हुआ था।

> $ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   index.html
#

git mvइसके बजाय का उपयोग करें ।

> $ git mv css/iphone.css css/mobile.css
> $ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   renamed:    css/iphone.css -> css/mobile.css
#
# 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:   index.html
#

लगता है हम अच्छे हैं। तो जब मैंने खोजक का उपयोग किया था तो पहली बार नाम बदलने के बारे में समझ क्यों नहीं आई?


29
Git सामग्री को ट्रैक करता है, फाइलों को नहीं, इसलिए इससे कोई फर्क नहीं पड़ता कि आप अपने सूचकांक को उचित स्थिति में कैसे लाते हैं - add+rmया mv- यह एक ही परिणाम उत्पन्न करता है। Git तो इसका नाम बदलने के लिए इसका नाम / प्रतिलिपि पहचान का उपयोग करता है। आपके द्वारा उद्धृत स्रोत भी गलत है। यह वास्तव में कोई फर्क नहीं पड़ता है कि आप एक ही प्रतिबद्ध में + नाम बदलें या नहीं। जब आप संशोधित और नाम बदलने दोनों में अंतर करते हैं, तो नाम का पता लगाना इसे एक नाम + संशोधन के रूप में देखेगा, या यदि संशोधन कुल पुनर्लेखन है, तो यह जोड़े और हटाए गए के रूप में दिखाई देगा - फिर भी कोई फर्क नहीं पड़ता कि आपने कैसे प्रदर्शन किया यह।
कैस्केबेल

6
अगर यह सच है, तो उसने फाइंडर का उपयोग करके अपने नाम का पता क्यों नहीं लगाया?
ग्रेग के

26
git mv old newस्वचालित रूप से सूचकांक को अद्यतन करता है। जब आप Git से बाहर का नाम बदलते हैं, तो आपको अनुक्रमणिका में परिवर्तनों को करने git add newऔर git rm oldकरने के लिए करना होगा । एक बार जब आप ऐसा कर लेते हैं तो git statusआप उम्मीद के मुताबिक काम करेंगे।
क्रिस जॉन्सन

4
मैं बस एक फाइल को एक public_htmlडायर में ले गया, जिसे गिट में ट्रैक किया गया है। प्रदर्शन करने के बाद git add .और git commit, यह अभी भी 'हटाई गई' फ़ाइलों का एक गुच्छा दिखाता है git status। मैंने प्रदर्शन किया git commit -aऔर विलोपन शुरू कर दिया गया था, लेकिन अब मैं उन फाइलों पर कोई इतिहास नहीं रखता जो public_htmlअब रहते हैं। यह कार्य प्रवाह उतना आसान नहीं है जितना मैं चाहूंगा।
ग्रेग के

जवाबों:


352

के लिए मैनुअल पेज का कहना हैgit mv

सफल समापन के बाद सूचकांक को अपडेट किया जाता है, […]

तो, सबसे पहले, आपको अपने दम पर (उपयोग करके git add mobile.css) सूचकांक को अपडेट करना होगा । हालांकि
git status अभी भी दो अलग-अलग फाइलें दिखाई देंगी

$ git status
# On branch master
warning: LF will be replaced by CRLF in index.html
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   index.html
#       new file:   mobile.css
#
# Changed but not updated:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       deleted:    iphone.css
#

आप रन करके एक अलग आउटपुट प्राप्त कर सकते हैं git commit --dry-run -a, जिसके परिणामस्वरूप आप अपेक्षा करते हैं:

Tanascius@H181 /d/temp/blo (master)
$ git commit --dry-run -a
# On branch master
warning: LF will be replaced by CRLF in index.html
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   index.html
#       renamed:    iphone.css -> mobile.css
#

मैं तुम्हें वास्तव में क्यों हम के बीच इन मतभेदों को देख नहीं बता सकता git statusऔर
git commit --dry-run -a, लेकिन यहां से एक संकेत है लीनुस :

git वास्तव में आंतरिक रूप से पूरे "नाम का पता लगाने" के बारे में भी परवाह नहीं करता है , और आपने जो भी नाम बदला है, उसके साथ किए गए कोई भी पुर्नजन्म पूरी तरह से स्वतंत्र हैं जिन्हें हम नाम बदलने के लिए उपयोग करते हैं

एक dry-runवास्तविक नामकरण तंत्र का उपयोग करता है, जबकि git statusशायद नहीं करता है।


1
आप उस चरण का उल्लेख करने में विफल रहे जहां आपने किया था git add mobile.css। इसके बिना git status -aपहले से ट्रैक की गई iphone.cssफ़ाइल को हटाने के लिए केवल 'देखा' होगा, लेकिन नई, अनट्रैक mobile.cssफ़ाइल को नहीं छुआ होगा । इसके अलावा, git status -aGit 1.7.0 और बाद में अमान्य है। "Git स्टेटस" अब "git प्रतिबद्ध --dry-run" नहीं है। में kernel.org/pub/software/scm/git/docs/RelNotes-1.7.0.txtgit commit --dry-run -aयदि आप यह कार्यक्षमता चाहते हैं, तो उपयोग करें । जैसा कि दूसरों ने कहा है, बस इंडेक्स को अपडेट करें और git statusओपी को उम्मीद है कि यह काम करेगा।
क्रिस जॉन्सन

3
यदि आप एक सामान्य करते हैं तो git commitयह पुनर्नामित फ़ाइल नहीं करेगा और काम करने वाला पेड़ अभी भी वैसा ही है। git commit -aगित के वर्कफ़्लो / थिंकिंग मॉडल के हर पहलू को बहुत हरा देता है - प्रत्येक परिवर्तन प्रतिबद्ध है। क्या होगा यदि आप केवल फ़ाइल का नाम बदलना चाहते हैं, लेकिन index.htmlदूसरी कमेटी में बदलाव करें ?
knittl

@ क्रिस: हाँ, निश्चित रूप से मैंने जोड़ा mobile.cssजो मुझे उल्लेख करना चाहिए था। लेकिन यह मेरे जवाब की बात है: मैन पेज कहता है कि the index is updatedजब आप उपयोग करते हैं git-mvstatus -aस्पष्टीकरण के लिए धन्यवाद , मैंने
१.२.४ पर

4
बहुत बढ़िया जवाब! मैं दीवार के खिलाफ अपना सिर पीट रहा था ताकि यह git statusपता लगाने की कोशिश करूं कि नाम बदलने का पता क्यों नहीं चल रहा था। git commit -a --dry-runमेरी "नई" फाइलों को जोड़ने के बाद रनिंग ने नाम बदलकर दिखाया और आखिरकार मुझे कमिट करने का भरोसा दिया!
Stephen.hanson

1
Git 1.9.1 में git statusअब ऐसा व्यवहार करता है git commit
जैक्स रेने मेसरिन

77

Git को एक चाल के रूप में पहचानने से पहले आपको दो संशोधित फ़ाइलों को अनुक्रमणिका में जोड़ना होगा।

केवल इतना अंतर है mv old newऔर git mv old newयह है कि git mv भी ​​फाइलों को इंडेक्स में जोड़ता है।

mv old newतब git add -Aभी काम किया होगा।

ध्यान दें कि आप सिर्फ git add .इसलिए उपयोग नहीं कर सकते क्योंकि यह इंडेक्स में रिमूवल नहीं जोड़ता है।

"गिट ऐड-ए" और "गिट ऐड" के बीच अंतर देखें


3
git add -Aलिंक के लिए धन्यवाद , बहुत उपयोगी, जैसा कि मैं इस तरह के शॉर्टकट के लिए देख रहा था!
फील्हो

5
ध्यान दें कि Git 2 के साथ, git add . करता सूचकांक को निकालने की प्रक्रिया जोड़ें।
निक मैक्युरी जुले

19

सबसे अच्छी बात यह है कि इसे अपने लिए आजमाएं।

mkdir test
cd test
git init
touch aaa.txt
git add .
git commit -a -m "New file"
mv aaa.txt bbb.txt
git add .
git status
git commit --dry-run -a

अब git स्टेटस और git कमिट --dry-run -a दो अलग-अलग परिणाम दिखाता है जहाँ git स्टेटस bbb.txt को एक नई फ़ाइल / aaa.txt के रूप में दिखाता है, और --dry-run कमांड वास्तविक नाम दिखाता है।

~/test$ git status

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   bbb.txt
#
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   deleted:    aaa.txt
#


/test$ git commit --dry-run -a

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   renamed:    aaa.txt -> bbb.txt
#

अब आगे बढ़ें और चेक-इन करें।

git commit -a -m "Rename"

अब आप देख सकते हैं कि फ़ाइल का वास्तव में नाम बदल दिया गया है, और गिट स्थिति में जो दिखाया गया है वह गलत है।

कहानी का नैतिक: यदि आप सुनिश्चित नहीं हैं कि आपकी फ़ाइल का नाम बदला गया है, तो "git कमिट --dry-run -a" जारी करें। यदि यह दिखा रहा है कि फ़ाइल का नाम बदला गया है, तो आप जाने के लिए अच्छे हैं।


3
Git के लिए क्या मायने रखता है, दोनों ही सही हैं । उत्तरार्द्ध कैसे आप के करीब हो रहा है, जैसा कि कमिटर शायद इसे देखते हैं, हालांकि। असली के बीच नाम बदलने और हटाने + बनाने के अंतर केवल ओएस / फाइल सिस्टम के स्तर पर (जैसे एक ही आईनोड # बनाम नई inode #) है, जो Git वास्तव में बहुत ज्यादा के बारे में परवाह नहीं करता है।
एलोइस महदाल

17

Git 1.7.x के लिए निम्नलिखित कमांड्स ने मेरे लिए काम किया:

git mv css/iphone.css css/mobile.css
git commit -m 'Rename folder.' 

Git ऐड की कोई आवश्यकता नहीं थी, क्योंकि मूल फ़ाइल (यानी css / mobile.css) पहले से ही प्रतिबद्ध फाइलों में थी।


6
इस। अन्य सभी उत्तर हास्यास्पद और अनावश्यक रूप से जटिल हैं। यह फ़ाइल इतिहास को कमिट्स के बीच बनाए रखता है ताकि फ़ाइल का नाम बदलने से पहले / बाद में विलय न हो।
फुलचेस

10

आपके पास git add css/mobile.cssनई फ़ाइल है और git rm css/iphone.cssइसलिए git इसके बारे में जानता है। तब यह उसी आउटपुट को दिखाएगाgit status

आप इसे स्थिति आउटपुट (फ़ाइल का नया नाम) में स्पष्ट रूप से देख सकते हैं:

# Untracked files:
#   (use "git add <file>..." to include in what will be committed)

और (पुराना नाम):

# Changed but not updated:
#   (use "git add/rm <file>..." to update what will be committed)

मुझे लगता है कि पर्दे के पीछे git mvएक रैपर स्क्रिप्ट के अलावा और कुछ नहीं है जो वास्तव में ऐसा करता है: फ़ाइल को इंडेक्स से हटा दें और इसे अलग नाम से जोड़ें


मुझे नहीं लगता था कि मुझे ऐसा करना पड़ा git rm css/iphone.cssक्योंकि मुझे लगा कि यह मौजूदा इतिहास को हटा देगा। शायद मैं git में वर्कफ़्लो को गलत समझ रहा हूं।
ग्रेग के

4
@Greg K: git rmइतिहास को नहीं हटाएगा। यह केवल इंडेक्स से एक प्रविष्टि को हटाता है ताकि अगली प्रतिबद्ध में प्रविष्टि न हो। हालाँकि, यह अभी भी पैतृक आवागमन में मौजूद होगा। आप जिसके बारे में भ्रमित हो सकते हैं, वह यह है कि (उदाहरण के लिए) git log -- newउस बिंदु पर रुक जाएगा जहां आपने प्रतिबद्ध किया था git mv old new। यदि आप नाम बदलना चाहते हैं, तो उपयोग करें git log --follow -- new
क्रिस जॉन्सन

9

आइए आपकी फ़ाइलों के बारे में विचार करें।

ध्यान रखें कि गिट आपकी फाइलों के बारे में कोई मेटाडेटा ट्रैक नहीं करता है

आपकी रिपॉजिटरी में (दूसरों के बीच)

$ cd repo
$ ls
...
iphone.css
...

और यह नियंत्रण के अधीन है:

$ git ls-files --error-unmatch iphone.css &>/dev/null && echo file is tracked
file is tracked

इसके साथ परीक्षण करें:

$ touch newfile
$ git ls-files --error-unmatch newfile &>/dev/null && echo file is tracked
(no output, it is not tracked)
$ rm newfile

जब तुम करोगे

$ mv iphone.css mobile.css

Git के नजरिए से,

  • कोई iphone.css नहीं है (इसे हटा दिया जाता है -It उस बारे में चेतावनी देता है-)।
  • एक नई फ़ाइल mobile.css है
  • वे फाइलें पूरी तरह से असंबंधित हैं।

तो, git उन फाइलों के बारे में सलाह देता है जो पहले से ही जानता है ( iphone.css ) और नई फ़ाइलें जो यह पता लगाता है ( mobile.css ) लेकिन केवल जब फाइलें इंडेक्स में होती हैं या HEAD git उनकी सामग्री की जांच करना शुरू करता है।

इस समय, न तो "iphone.css विलोपन" और न ही mobile.css इंडेक्स पर हैं।

अनुक्रमणिका के लिए iphone.css विलोपन जोड़ें

$ git rm iphone.css

git आपको बताता है कि वास्तव में क्या हुआ है: ( iphone.cs हटा दिया गया है। अधिक कुछ नहीं हुआ)

फिर नई फ़ाइल mobile.css जोड़ें

$ git add mobile.css

इस बार डिलीट और नई फाइल दोनों इंडेक्स पर हैं। अब git का संदर्भ संदर्भ समान है और इसे एक नाम के रूप में उजागर करता है। वास्तव में अगर फाइलें 50% समान हैं, तो यह पता चलेगा कि नाम बदलने के रूप में, जिससे आप मोबाइल को बदल सकें । ऑपरेशन को नाम बदलने के दौरान थोड़ा सा रखें

देखें यह प्रजनन योग्य है git diff। अब जब आपकी फाइलें इंडेक्स पर हैं तो आपको इसका उपयोग करना होगा --cachedMobile.css को संपादित करें , उस अनुक्रमणिका में जोड़ें और उसके बीच का अंतर देखें:

$ git diff --cached 

तथा

$ git diff --cached -M

-Mके लिए "नाम का पता लगाने" विकल्प है git diff। (50% या अधिक समानता -Mके लिए खड़ा है, -M50%यह एक नाम बदलने के रूप में व्यक्त करेगा) लेकिन आप इसे -M20%(20%) कम कर सकते हैं यदि आप मोबाइल को संपादित करते हैं। बहुत कुछ।


8

Step1: फ़ाइल को पुराने फ़ाइल से नया फ़ाइल में नाम बदलें

git mv #oldfile #newfile

Step2: कमिट करें और टिप्पणी जोड़ें

git commit -m "rename oldfile to newfile"

Step3: इस परिवर्तन को दूरस्थ रूप से धकेलें

git push origin #localbranch:#remotebranch

1
कृपया कुछ टिप्पणी जोड़ें ताकि यह ओपी के लिए उपयोगी हो
देवराठ

चरण 2 अनावश्यक है। बाद git mv, नई फ़ाइल पहले से ही इंडेक्स में है।
एलोइस महदाल

7

Git किसी नई अनट्रैक फ़ाइल के रूप में देखने के बजाय, सामग्री से फ़ाइल को पहचान लेगा

यहीं तुम गलत हो गए।

इसके बाद ही हैफ़ाइल जोड़ने के , यह git सामग्री से इसे पहचान लेगा।


बिल्कुल सही। जब मंचित git नाम सही रूप से दिखाएगा।
मैक्स मैकलेओड

3

आपने अपने खोजक के परिणामों को चरणबद्ध नहीं किया। मेरा मानना ​​है कि अगर आपने फाइंडर के माध्यम से कदम उठाया और फिर किया git add css/mobile.css ; git rm css/iphone.css, तो git नई फाइल के हैश की गणना करेगा और उसके बाद ही पता चलेगा कि फाइल्स की हैश मैच (और इस तरह यह एक नाम है)।


2

ऐसे मामलों में जहां आपको वास्तव में फ़ाइलों का नाम बदलना पड़ता है, उदाहरण के लिए। एक स्क्रिप्ट का उपयोग करके फ़ाइलों का एक गुच्छा नाम बदलें, फिर git add -A .मेरे लिए काम करना।


2

Xcode उपयोगकर्ताओं के लिए: यदि आपकी फ़ाइल का नाम Xcode में बदल दिया जाता है, तो आपको एपेंड करने के लिए बैज आइकन परिवर्तन दिखाई देता है। यदि आप XCode का उपयोग करते हुए कमिट करते हैं तो आप वास्तव में एक नई फ़ाइल बनाएंगे और इतिहास खो देंगे।

वर्कअराउंड आसान है, लेकिन आपको Xcode का उपयोग करने से पहले इसे करना होगा:

  1. अपने फोल्डर पर git स्टेटस करें। आपको यह देखना चाहिए कि चरणबद्ध परिवर्तन सही हैं:

नाम बदला: परियोजना / पुराना नाम। -> परियोजना / नया नाम। नाम बदला: परियोजना / पुराना नाम -> परियोजना / नया नाम।

  1. कमिट-एम 'नाम परिवर्तन'

फिर XCode पर वापस जाएं और आपको A से M में बदला हुआ बैज दिखाई देगा और यह अब Xcode का उपयोग करने के लिए उग्र बदलाव करने से बचा है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.