Git'te dosya adlarını işleme


440

Git'te dosyaları yeniden adlandırırken , herhangi bir değişiklik yapmanız, yeniden adınızı gerçekleştirmeniz ve ardından yeniden adlandırılmış dosyanızı sahnelemeniz gerektiğini okudum . Git dosyayı izlenmeyen yeni bir dosya olarak görmek yerine içerikten tanıyacak ve değişiklik geçmişini saklayacaktır.

Ancak, sadece bu gece yaptığım dönmeye geri döndüm git mv.

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

Dan Finder benim stil yeniden adlandırma iphone.cssiçinmobile.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 artık bir CSS dosyasını sildiğimi ve yeni bir tane eklediğimi düşünüyor. İstediğim gibi değil, yeniden adlandırmayı geri alalım ve git işini yapalım.

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

Başladığım yere geri döndüm.

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

git mvBunun yerine kullanalım .

> $ 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
#

Görünüşe göre iyiyiz. Peki neden Git'i ilk kez Finder'ı kullandığımda yeniden adlandırmayı tanımadı?


29
Git dosyaları değil içeriği izler, bu nedenle dizininizi doğru duruma nasıl getirdiğiniz önemli değildir - add+rmya mvda aynı sonucu verir. Git, daha sonra yeniden adlandırıldığını bildirmek için yeniden adlandırma / kopya algılama özelliğini kullanır. Alıntıladığınız kaynak da yanlış. Aynı taahhüdde değiştirip değiştirmemeniz önemli değildir. Hem değiştirme hem de yeniden adlandırma arasında bir fark yaptığınızda, yeniden adlandırma algılaması bunu yeniden adlandırma + değişiklik olarak görür veya değişiklik toplam yeniden yazma ise, eklenmiş ve silinmiş olarak gösterilir - yine de nasıl yaptığınız önemli değildir o.
Cascabel

6
Bu doğruysa, Finder'ı kullanarak neden yeniden adımı kullanarak algılamadı?
Greg K

26
git mv old newdizini otomatik olarak günceller. Git dışında yeniden adlandırdığınızda, git add newve git rm olddizinindeki değişiklikleri yapmak için ve öğelerini yapmanız gerekir . Bunu yaptıktan sonra git statusbeklediğiniz gibi çalışacaktır.
Chris Johnsen

4
Bir sürü dosyayı public_htmlgit'te izlenen bir dizine taşıdım . Gerçekleştirilen olması git add .ve git commithala bir demet dosyaları 'silindi' gösterdi git status. Bir performans gerçekleştirdim git commit -ave silme işlemleri gerçekleştirildi , ancak şimdi içinde yaşayan dosyalar üzerinde hiçbir geçmişim yok public_html. Bu iş akışı istediğim kadar pürüzsüz değil.
Greg K

Yanıtlar:


352

İçin kılavuz sayfası diyorgit mv

Dizin başarılı bir şekilde tamamlandıktan sonra güncellenir, […]

Bu nedenle, ilk önce, dizini kendi başınıza güncellemeniz gerekir (kullanarak git add mobile.css). Ancak
git status yine de iki farklı dosya gösterilecek

$ 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
#

Çalıştırarak farklı bir çıktı elde edebilirsiniz git commit --dry-run -a, bu da beklediğinizle sonuçlanır:

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
#

Size git statusve arasındaki bu farkları tam olarak neden gördüğümüzü tam olarak söyleyemem
git commit --dry-run -a, ancak işte Linus'un bir ipucu :

git gerçekten "yeniden adlandırma algılamasını" dahili olarak umursamıyor ve adlarla yaptığınız herhangi bir taahhüt, daha sonra yeniden adlandırmaları göstermek için kullandığımız buluşsal yöntemlerden tamamen bağımsızdır .

A dry-run, gerçek yeniden adlandırma mekanizmalarını kullanır, ancak git statusmuhtemelen kullanmaz.


1
Yaptığınız adımdan bahsetmediniz git add mobile.css. Olmadan git status -asadece önceden izlenen iphone.cssdosyanın kaldırılmasını 'görürdü', ancak yeni, izlenmemiş mobile.cssdosyaya dokunmazdı . Ayrıca git status -aGit 1.7.0 ve sonraki sürümlerinde geçersizdir. "" Git status "artık" git commit --dry-run "değil." içinde kernel.org/pub/software/scm/git/docs/RelNotes-1.7.0.txt . git commit --dry-run -aBu işlevi istiyorsanız kullanın . Diğerlerinin söylediği gibi, dizini güncelleyin git statusve OP'nin beklediği gibi çalışın.
Chris Johnsen

3
normal yaparsanız git commit, yeniden adlandırılan dosyayı işlemez ve çalışma ağacı hala aynıdır. git commit -agit'in iş akışı / düşünme modelinin hemen hemen her yönünü yener - her değişiklik yapılır. yalnızca dosyayı yeniden adlandırmak, ancak index.htmlbaşka bir işlemde değişiklik yapmak istiyorsanız ne olur ?
knittl

@Chris: evet, elbette mobile.cssbahsetmem gerekenleri ekledim . Ama bu benim cevap nokta: man sayfası söylüyor the index is updatedkullandığınızda git-mv. status -aAçıklama için teşekkürler , git 1.6.4
tanascius

4
Mükemmel cevap! git statusYeniden adlandırma nedenini tespit etmediğini anlamaya çalışırken başımı duvara vuruyordum. git commit -a --dry-runBenim "yeni" dosyaları ekledikten sonra çalışan isimleri gösterdi ve nihayet bana taahhüt için güven verdi!
stephen.hanson

1
Git 1.9.1 git statusşimdi gibi davranıyor git commit.
Jacques René Mesrine

77

Git dosyayı bir hareket olarak tanımadan önce değiştirilmiş iki dosyayı dizine eklemeniz gerekir.

Arasındaki tek fark mv old newve git mv old newgit mv da dizine dosyaları ekler olmasıdır.

mv old newo git add -Azaman da işe yarardı.

Yalnızca git add .dizine kaldırma eklemediğinden kullanamayacağınızı unutmayın .

Bkz. "Git add -A" ve "git add" arasındaki fark.


3
git add -ABağlantı için teşekkürler , çok kullanışlı, böyle bir kısayol arıyordum!
PhiLho

5
Git 2 ile, o Not git add . gelmez endekse kaldırma ekleyin.
Nick McCurdy

19

En iyisi kendiniz denemek.

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

Şimdi git status ve git command --dry-run -a, git durumunun bbb.txt dosyasını yeni bir dosya / aaa.txt silindiğinde gösterdiği ve --dry-run komutlarının gerçek yeniden adlandırmayı gösterdiği iki farklı sonuç gösterir.

~/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
#

Şimdi devam edin ve check-in yapın.

git commit -a -m "Rename"

Artık dosyanın aslında yeniden adlandırıldığını ve git durumunda gösterilenlerin yanlış olduğunu görebilirsiniz.

Hikayenin ahlakı: Dosyanızın yeniden adlandırılıp adlandırılmadığından emin değilseniz, bir "git commit --dry-run -a" yayınlayın. Dosyanın yeniden adlandırıldığını gösteriyorsa, hazırsınız demektir.


3
Git için önemli olan her ikisi de doğrudur . İkincisi, komünerin muhtemelen gördüğünüz gibi, size daha yakın olmaktır. Gerçek Yeniden adlandırma ile + delete oluşturmak arasındaki fark Git gerçekten çok umursamıyor sadece OS / dosya sistemi düzeyinde (yeni inode # vs gibi aynı inode #) vardır.
Alois Mahdal

17

Git 1.7.x için aşağıdaki komutlar benim için çalıştı:

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

Orijinal dosya (örn. Css / mobile.css) önceden kaydedilmiş dosyalarda olduğu için git add'e gerek yoktu.


6
Bu. Diğer tüm cevaplar gülünç ve gereksiz yere karmaşıktır. Bu işlem, dosya yeniden adlandırma işleminden önce / sonra birleştirilmemesi için komutlar arasındaki dosya geçmişini korur.
Phlucious

10

Mecbur git add css/mobile.cssyeni dosya ve git rm css/iphone.cssgit bunu biliyor, bu yüzden. aynı çıktıyıgit status

bunu durum çıktısında (dosyanın yeni adı) açıkça görebilirsiniz:

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

ve (eski ad):

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

sahne arkasında git mvtam olarak yapan bir sarıcı komut dosyası başka bir şey olduğunu düşünüyorum : dizinden dosyayı silmek ve farklı bir ad altında ekleyin


Yapmam gerektiğini düşünmemiştim, git rm css/iphone.cssçünkü bunun mevcut tarihi kaldıracağını düşündüm. Belki git'teki iş akışını yanlış anlıyorum.
Greg K

4
@Greg K: git rmgeçmişi kaldırmayacak. Bir dizinden yalnızca bir girdiyi kaldırır, böylece bir sonraki işlem girdiye sahip olmaz. Ancak, ataların taahhütlerinde hala var olacaktır. Kafanız karışmış olabileceği şey (örneğin) git log -- newtaahhüt ettiğiniz noktada duracaktır git mv old new. Yeniden adlarını takip etmek istiyorsanız tuşunu kullanın git log --follow -- new.
Chris Johnsen

9

Dosyalarınızı git perspektifinden düşünelim.

Unutmayın, dosyalarınızla ilgili herhangi bir meta veri izlemez

Deponuzda (diğerleri arasında) var

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

ve git kontrolü altında:

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

Bunu aşağıdakilerle test edin:

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

Ne zaman yaparsın

$ mv iphone.css mobile.css

Git perspektifinden bakıldığında,

  • iphone.css yoktur (silinir -git bu konuda uyarır-).
  • mobile.css adlı yeni bir dosya var .
  • Bu dosyalar tamamen alakasız.

Git, zaten bildiği dosyalar ( iphone.css ) ve algıladığı yeni dosyalar ( mobile.css ) hakkında bilgi verir, ancak yalnızca dosyalar dizinde veya HEAD git içeriğini kontrol etmeye başladığında.

Şu anda ne "iphone.css silme" ne de mobile.css dizinde bulunmuyor .

Dizine iphone.css silme ekle

$ git rm iphone.css

git size tam olarak ne olduğunu söyler: ( iphone.css silinir. Başka bir şey olmadı)

ardından mobile.css adlı yeni bir dosya ekleyin

$ git add mobile.css

Bu kez hem silme hem de yeni dosya dizinde. Git git, bağlamın aynı olduğunu algılar ve yeniden adlandırma olarak gösterir. Aslında dosyalar% 50 benzer ise, bir yeniden adlandırma olarak algılar, bu da işlemi yeniden adlandırma olarak tutarken mobile.css'yi biraz değiştirmenize izin verir .

Bunun yeniden üretilebildiğine bakın git diff. Artık dosyalarınız dizinde --cached. Düzenleme mobile.css biraz endekse eklemek ve arasındaki farkı görmek:

$ git diff --cached 

ve

$ git diff --cached -M

-Miçin "yeniden adlandırmaları algıla" seçeneğidir git diff. -Mkısaltmasıdır -M50%(% 50 veya daha fazla benzerlik git'i bir yeniden adlandırma olarak ifade etmesini sağlar) ancak -M20%mobile.css dosyasını çok düzenlerseniz bunu (% 20) değerine düşürebilirsiniz .


8

Adım 1: Dosyayı eski dosyadan yeni dosyaya yeniden adlandırın

git mv #oldfile #newfile

2.Adım: Git ve yorum ekleyin

git commit -m "rename oldfile to newfile"

3.Adım: Bu değişikliği uzak sunucuya aktarın

git push origin #localbranch:#remotebranch

1
Lütfen
OP'ye

Adım 2 gerekli değildir. Sonra git mv, yeni dosya zaten dizinde.
Alois Mahdal

7

Git dosyayı izlenmeyen yeni bir dosya olarak görmek yerine içerikten tanıyacaktır

Yanlış yaptığınız yer burası.

Yalnızca dosyayı ekledikten sonra , git dosyayı içerikten tanıyacaktır.


Kesinlikle. Hazırlandığında git yeniden adlandırmayı doğru gösterecektir.
Max MacLeod

3

Bulucu hareketinin sonuçlarını sahnelemedin. Eğer Finder ile hareket yaptıysanız ve sonra yaptıysanız git add css/mobile.css ; git rm css/iphone.css, git yeni dosyanın hash hesaplamak ve ancak daha sonra dosyaların hashes eşleşen (ve böylece bir yeniden adlandırma) fark inanıyorum.


2

Örneğin dosyaları manuel olarak yeniden adlandırmanız gereken durumlarda, örneğin. bir grup dosyayı toplu olarak yeniden adlandırmak için bir komut dosyası kullanarak, sonra kullanarak git add -A .benim için çalıştı.


2

Xcode kullanıcıları için: Dosyanızı Xcode'da yeniden adlandırırsanız, rozet simgesinin ekleneceğini görürsünüz. XCode kullanarak bir taahhütte bulunursanız, aslında yeni bir dosya oluşturur ve geçmişi kaybedersiniz.

Bir çözüm kolaydır, ancak Xcode'u kullanmaya başlamadan önce yapmanız gerekir:

  1. Klasörünüzde bir Git Durumu yapın. Aşamalı değişikliklerin doğru olduğunu görmelisiniz:

yeniden adlandırıldı: Project / OldName.h -> Project / NewName.h yeniden adlandırıldı: Project / OldName.m -> Project / NewName.m

  1. taahhüt -m 'isim değişikliği'

Sonra XCode'a geri dönün ve rozetin A'dan M'ye değiştiğini göreceksiniz ve şimdi xcode kullanımında daha fazla değişiklik yapmak için kaydedildi.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.