Git'te bir dosyayı açmanın neden iki yolu vardır?


1169

Bazen git git rm --cachedbazen bir dosyayı bozmayı önerir git reset HEAD file. Hangisini ne zaman kullanmalıyım?

DÜZENLE:

D:\code\gt2>git init
Initialized empty Git repository in D:/code/gt2/.git/
D:\code\gt2>touch a

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       a
nothing added to commit but untracked files present (use "git add" to track)

D:\code\gt2>git add a

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   a
#
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a

D:\code\gt2>touch b

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

D:\code\gt2>git add b

D:\code\gt2>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   b
#

20
Neden? Bunun nedeni, git'in komut satırı arabiriminin organik olarak geliştiği ve işleri tutarlı hale getirmek için hiçbir zaman büyük bir yeniden yapılandırmaya tabi olmadığı için söyleyebilirim. (Eğer kabul etmiyorsanız, not nasıl git rmedebileceğimiz sahne bir silme de ve unstage bir ek )
Roman Starkov

3
@romkyns: Git'in arayüzünün organik olarak geliştiği için birkaç tuhaflığı olduğu konusunda hemfikirim, ancak kaldırma işlemi kesinlikle bir eklemenin tersi bir işlevdir, bu yüzden rmgeri almak mantıklı değil addmi? Sizce nasıl rmdavranmalı?
Zaz

6
Bir sonraki sorunuza sadece gerçek cevabı bu doğru git inithiçbir orada HEADsıfırlamak için.
Miles Rout


4
@Zaz, fikrimi vereceğim. rmunix bağlamında silme anlamına gelir. Dizine eklemenin tersi değildir. Dosyaları kaldırma işlevi, hazırlama durumunu değiştirme işlevleriyle aşırı yüklenmemelidir. Bunları birleştirmeyi kolaylaştıran uygulama detayları varsa, git'te düşünülebilir bir soyutlama katmanının bulunmamasına işaret eder, bu da kullanılabilirliği açık hale getirir.
Joshua Goldberg

Yanıtlar:


1893

git rm --cached <filePath> bir dosyayı bozmazsa , aslında dosya (lar) ın depodan kaldırılmasını aşamalar (daha önce kaydedilmiş olduğu varsayılarak), ancak dosyayı çalışma ağacınızda bırakır (sizi izlenmeyen bir dosya ile bırakır).

git reset -- <filePath>olacaktır unstage herhangi bir dosya (lar) için değişiklikler yaptı.

Bununla git rm --cachedbirlikte, aşamalı yeni bir dosyada kullandıysanız, daha önce hiç taahhüt edilmemiş olduğu için, temelde dosyayı henüz kaldırmamış gibi görünecektir.

Güncelleme git 2.24 Git'in
bu yeni sürümünde git restore --stagedbunun yerine kullanabilirsiniz git reset. Git belgelerine bakın .


71
git rm --cachedDosyanın etkisizliğini söyleyebilirim , ancak çalışma dizininden kaldırmaz.
Pierre de LESPINAY

4
Artık eklenmeyecek şekilde eklenmek üzere hazırlanmış bir dosyayı kaldırmak için mutlaka "eklenmek üzere hazırlanmış bir dosyanın etiketini kaldırma" olarak adlandırılabilir, değil mi? Sonuç aşamalı bir silme değildir , bu kesinlikle, bu yüzden yanlış anlama tamamen anlaşılabilir olduğunu düşünüyorum.
Roman Starkov

4
Bu nedenle, tipik olarak, hiçbir zaman repoda olmaması gerektiğini fark ettikten sonragit rm --cached <filePath> bazı dosyaları depodan kaldırmak için kullanılır : bu nedenle büyük olasılıkla bu komutu çalıştırıp ilgili dosyaları ekler . Doğrumuyum? gitignore
Adrien Be

13
Hem soru hem de cevap üzerine bu kadar çok oyla, görünüşe göre bir unstageemir almak istediğimizi söyleyebilirim git.
milosm

4
"git status" şu an için tavsiyede bulunuyor: "git restore --staged <file> ..." işlevini kullandı
yucer

334

git rm --cachedbir dosyayı dizinden kaldırmak için kullanılır. Dosyanın zaten repoda olması durumunda, dosyayı git rm --cacheddizinden kaldıracak, çalışma dizininde bırakacak ve bir taahhüt artık repodan da kaldıracaktır. Temel olarak, taahhütten sonra dosyayı tersine çevirip yerel bir kopyasını saklardınız.

git reset HEAD file(varsayılan olarak --mixedbayrağı kullanıyor ), dosyanın zaten repoda olması durumunda farklıdır, dosyanın dizin sürümünü, repo (HEAD) ile değiştirir ve değişiklikler üzerinde etkin bir şekilde değiştirir .

Sürümsüz dosya durumunda, dosya HEAD'de olmadığından dosyanın tamamını bozar. Bu açıdan git reset HEAD fileve git rm --cachedaynılar, ancak aynı değiller (repoda zaten dosyalarda açıklandığı gibi)

Sorusuna Why are there 2 ways to unstage a file in git?- GIT'de şey yapmak için tek bir yol gerçekten hiç olmaz ki. Bu onun güzelliği :)


7
Hem kabul edilen cevap hem de bu harika ve neden birini diğerine karşı kullanacağınızı açıklayın. Ancak git neden iki farklı yöntem önerdiğinin örtük sorusuna doğrudan cevap vermezler . OP örneğindeki ilk durumda, bir git init henüz yapılmıştır. Bu durumda git "git rm --cached" komutunu önerir çünkü o noktada depoda taahhüt yoktur ve bu nedenle HEAD geçerli değildir. "git reset HEAD - a" üretir: "ölümcül: 'HEAD' geçerli bir başvuru olarak çözümlenemedi."
sootsnoot

5
'git checkout' ile, dosyada yaptığınız tüm değişiklikleri kaybetmez misiniz?
John Deighan

there is never really only one way to do anything in git. that is the beauty of it- HIM neden ? tek bir bariz yol olduğunda her zaman harikadır. Bu, zamanımızın ve beyindeki hafızamızın çoğunu kurtarır))
Oto Shavadze

128

Oldukça basit:

  • git rm --cached <file> git'in dosyayı tamamen izlemeyi durdurmasını sağlar (düz git rm* ' ten farklı olarak dosya sisteminde bırakılır )
  • git reset HEAD <file> son işlemden bu yana dosyada yapılan değişikliklerden etkilenmez (ancak dosya adında, komut adının önerebileceğinin tersine döndürmez **). Dosya revizyon kontrolü altında kalır.

Dosya daha önce revizyon denetiminde değilse (yani git add, ilk kez edindiğiniz bir dosyayı kaldırıyorsanız ), iki komut aynı etkiye sahiptir, dolayısıyla bunların görünümü "bir şey yapmanın iki yolu" ".

* @DrewT'nin git rm --cacheddaha önce depoya işlenmiş bir dosyayla ilgili cevabından bahsettiğini unutmayın . Bu soru bağlamında henüz eklenmemiş ve henüz işlenmemiş bir dosya için endişelenecek bir şey yok.

** Git sıfırlama komutunu adı nedeniyle kullanmaktan utanç verici derecede uzun bir süre korktum - ve bugün hala sıkılmamaya emin olmak için sözdizimine bakıyorum. ( güncelleme : Sonunda bir tldr sayfasında kullanımını özetlemeyegit reset zaman ayırdım , bu yüzden şimdi nasıl çalıştığına dair daha iyi bir zihinsel modelim ve bazı ayrıntıları unuttuğumda hızlı bir referansım var.)


It'sgit rm <file> --cached
neonmate

8
Ben gerçekten bu cevaba 4 Ağustos 2015 düzenleme genel bir gelişme olduğunu sanmıyorum . Teknik doğruluğu düzeltmiş olabilir (bunu değerlendirmek için nitelikli hissetmiyorum), ancak korkuyorum ki şu anda izlenmeyen bir dosyayı izlemeye başlamak için zorunlu olan ayarları kaldırıyor "ve" index "ve" HEAD "gibi jargon kullanarak, tam olarak yeni başlayanları korkutan şeyler. Birisi yapabiliyorsa, daha yeni gelen bir dili geri yüklemek için lütfen düzenleyin.
waldyrious

5
@Waldyrious ile aynı fikirde. Orijinal cevap git ders kitabından çıkmış olmayabilir, ancak soruyu yeterli teknik düzeyde yanıtladı. Teknik ayrıntılar, orijinal amacı gizleyen bir düzenleme olarak değil, yorumlarda açıklığa kavuşturulmuş olmalıdır.
Simon Robb

Düzenlemeyi geri aldım. Topluluk tarafından (önceki yorumlarda ve onlara verilen oylarda) düzenlemenin cevabın netliğine zarar verdiğine dair yeterli doğrulama olduğuna inanıyorum.
waldyrious

Not @DrewT, kullanarak rm --cachedve itiyorsa , aynı dalı çeken herkesin dosya (lar) ı gerçekten çalışma ağacından çıkaracağı konusunda uyarır .
Tom Hale

53

Bu iş parçacığı biraz eski, ama yine de sezgisel bir sorun olmadığından hala küçük bir gösteri eklemek istiyorum:

me$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   to-be-added
#   modified:   to-be-modified
#   deleted:    to-be-removed
#

me$ git reset -q HEAD to-be-added

    # ok

me$ git reset -q HEAD to-be-modified

    # ok

me$ git reset -q HEAD to-be-removed

    # ok

# or alternatively:

me$ git reset -q HEAD to-be-added to-be-removed to-be-modified

    # ok

me$ git status
# On branch master
# 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)
#
#   modified:   to-be-modified
#   deleted:    to-be-removed
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   to-be-added
no changes added to commit (use "git add" and/or "git commit -a")

git reset HEAD(onsuz -q) değiştirilen dosya hakkında bir uyarı verir ve çıkış kodu komut dosyasında hata olarak kabul edilecek 1'dir.

Düzenleme: git checkout HEAD to-be-modified to-be-removedetiketleme için de çalışır, ancak değişikliği çalışma alanından tamamen kaldırır

Güncelleme git 2.23.0: Zaman zaman komutlar değişir. Şimdi git statusdiyor ki:

  (use "git restore --staged <file>..." to unstage)

... her üç değişiklik türü için de işe yarıyor


Teşekkürler, git reset ilk iki cevaptan (muhtemelen sadece terminoloji hakkındaki bilgisizlik) tamamen net değildi, dosyadaki değişiklikleri yerel olarak bıraktı (geri döndüren git çıkışının aksine).
soupdog

Eski sürüm yeni sürümlerdeki dosyaları sildiğinden, sürüm hakkında başlangıçta bir uyarı koymalısınız
Luis Mauricio

@LuisMauricio hangi komut dosyaları siler?
Daniel Alder

@DanielAlder sry, sadece tekrar test ettim, silmiyor, hatam.
Luis Mauricio

36

yanlışlıkla işlemek istemediğiniz dosyaları hazırladıysanız ve değişiklikleri sakladığınızdan emin olmak istiyorsanız, şunları da kullanabilirsiniz:

git stash
git stash pop

bu HEAD'e bir sıfırlama gerçekleştirir ve değişikliklerinizi yeniden uygulayarak dosyaları tek tek işlem için yeniden ayarlamanıza olanak tanır. bu, çekme istekleri ( git stash ; git checkout -b <feature> ; git stash pop) için bir özellik dalı oluşturmayı unuttuysanız da yararlıdır .


3
Bu temiz bir çözüm ve "git rm" yazmaktan çok daha az endişe verici
Subimage

1
git stashilgili başka avantajları da vardır, çünkü reflog'da ileride kullanılabilecek girişler oluşturur. şüphe duyduğunuzda, devam edin ve yapın git stash(örneğin git stash save -u "WIP notes to self"('-u' herhangi bir yeni / izlenmemiş dosyayı saklamak için saklayın) ... sonra git reflog show stashsaklı işlemlerin listesini ve bunların sha'larını görmeye çalışın . alias likealias grs="git reflog show stash"
cweekly

15

Söz konusu dosya repo içindeyse ve sürüm denetimi altındaysa (daha önce kaydedilmiş vb.) Bu 2 komutun bazı küçük farklılıkları vardır:

  • git reset HEAD <file> yürürlükteki komut dosyasındaki dosyayı etkisiz hale getirir.
  • git rm --cached <file>gelecekteki taahhütler için dosyayı bozar. Tekrar eklenene kadar etiketsizdir git add <file>.

Ve önemli bir fark daha var:

  • Çalıştırdıktan git rm --cached <file>ve dalınızı uzaktan kumandaya ittikten sonra , dalınızı uzaktan kumandadan çeken herkes , yerel çalışma kümenizde dosyanın izini kaldırmasına rağmen (yani klasörden fiziksel olarak silinmez) dosyayı klasörlerinden GERÇEKTEN silinir.

Bu son fark, takımdaki her geliştiricinin farklı bir yapılandırmaya (yani farklı temel url, ip veya bağlantı noktası ayarı) sahip olduğu bir yapılandırma dosyası içeren projeler için önemlidir, bu nedenle git rm --cached <file>dalınızı çeken birini kullanıyorsanız manuel olarak yeniden yapılandırmayı oluşturursanız, bunları kendiniz gönderebilirsiniz ve ip ayarlarını (vb.) yeniden düzenleyebilirler, çünkü silme yalnızca dalınızı uzaktan kumandadan çeken kişileri etkiler.


10

Diyelim ki size stagebir dizinin tamamını ekleyelim git add <folder>, ancak bir dosyayı aşamalı listeden (yani, çalışırken oluşturulan listeyi git status) hariç tutmak ve değişiklikleri hariç tutulan dosyada tutmak (bir şey üzerinde çalışıyordunuz ve çalışmaya hazır değilsiniz, ancak işini kaybetmek istemezsin ...). Sadece şunu kullanabilirsiniz:

git reset <file>

Eğer çalıştırdığınızda git status, her ne olursa olsun dosya (lar) göreceksiniz resetolan unstagedve dosyaların geri kalanını addedhala stagedlistede.


10

1.

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   a

(değişmeden "git rm --cached ..." kullanın)

  • git bir işaretçiler sistemidir

  • işaretçinizi değiştirmek için henüz bir taahhüdünüz yok

  • 'dosyaları işaret edilen bölümden çıkarmanın ' tek yolu git'e değişiklikleri izlemesini söylediğin dosyaları kaldırmaktır

2.

D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 a

git taahhüt -ma

  • taahhüt ettin, ' kurtardın '

3.

D:\code\gt2>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   b
#

(bozulmadan "git reset HEAD ..." kullanın)

  • şu anda kodunuzda bir taahhütte bulundunuz
  • Şimdi size işlemek 'için işaretçi sıfırlama tasarrufu son için Geri döndürme arka '

1
Aslında bu, IMO'ya soruyu doğru cevaplayan tek cevaptır. Aslında 'git rm --cached' ve 'git reset HEAD' arasındaki farklar ne değil 'git neden ikisini de tutarsız bir şekilde seçenek olarak veriyor?' sizi hiç git initilk kez.
Miles Rout

5

Kimse git reflog ( http://git-scm.com/docs/git-reflog ) bahsetmedi şaşırdım :

# git reflog
<find the place before your staged anything>
# git reset HEAD@{1}

Reflog, yalnızca repodaki değişiklikleri izlemekle kalmayıp aynı zamanda kullanıcı eylemlerini de izler (ör. Çekme, farklı şubeye ödeme, vb.) Ve bu eylemlerin geri alınmasına izin veren bir git geçmişidir. Bu yüzden, dosyaları hatalı bir şekilde sahnelemek yerine, dosyaları sahnelemediğiniz noktaya geri dönebilirsiniz.

Bu benzerdir, git reset HEAD <file>ancak bazı durumlarda daha ayrıntılı olabilir.

Üzgünüz - sorunuzu gerçekten cevaplamıyor, ancak oldukça sık kullandığım bozulmamış dosyalara başka bir yolu işaret ediyorum (Ryan Stewart'ın cevabı ve waldyrious için çok beğeniyorum.);) Umarım yardımcı olur.


5

Sadece kullan:

git reset HEAD <filename>

Bu, dosyayı etkisiz hale getirir ve üzerinde yaptığınız değişiklikleri korur, böylece isterseniz şubeleri ve git addbu dosyaları başka bir şubeye değiştirebilirsiniz. Tüm değişiklikler korunur.


3

Bana öyle geliyor ki git rm --cached <file>, dosyayı bir ovanın git rm <file>her ikisinin de rm <file>yapacağı dizinden kaldırmadan dizinden kaldıran , tıpkı bir OS'nin sürümünü kaldırmadan dizinden kaldıracağı gibi .


1

Yalnızca 2.23 ve üstü sürümler için,

Bunun yerine bu önerilerden şunu kullanabilirsiniz git restore --staged <file>amacıyla unstagedosya (lar).


Her iki seçenek ile çalışır --stageyanı sıra --staged.
dhana1310
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.