Pertanyaan Mengapa ada 2 cara untuk melonggarkan file di git?


Terkadang git menyarankan git rm --cached untuk melumpuhkan file, kadang-kadang git reset HEAD file. Kapan saya harus menggunakannya?

EDIT:

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
#

833
2017-08-02 21:50


asal


Jawaban:


git rm --cached <filePath>  tidak di-unstage sebuah file, sebenarnya langkah penghapusan file (s) dari repo (dengan asumsi itu sudah dilakukan sebelumnya) tetapi meninggalkan file di pohon kerja Anda (meninggalkan Anda dengan file yang tidak terlacak).

git reset <filePath> akan di luar panggung setiap perubahan bertahap untuk file yang diberikan.

Yang mengatakan, jika Anda menggunakan git rm --cached pada file baru yang dipentaskan, pada dasarnya akan terlihat seperti Anda baru saja melanggarnya karena belum pernah dilakukan sebelumnya.


1361
2017-08-02 22:03



git rm --cached digunakan untuk menghapus file dari indeks. Dalam kasus di mana file sudah di repo, git rm --cached akan menghapus file dari indeks, meninggalkannya di direktori kerja dan komit sekarang akan menghapusnya dari repo juga. Pada dasarnya, setelah komit, Anda akan mengubah file dan menyimpan salinan lokal.

git reset HEAD file (yang secara default menggunakan --mixed flag) berbeda karena dalam kasus di mana file sudah di repo, itu menggantikan versi indeks file dengan yang dari repo (HEAD), efektif unstaging modifikasi untuk itu.

Dalam kasus file tidak berversi, itu akan unstage seluruh file karena file itu tidak ada di HEAD. Dalam aspek ini git reset HEAD file dan git rm --cached sama, tetapi tidak sama (seperti yang dijelaskan dalam kasus file yang sudah di repo)

Untuk pertanyaan tentang Why are there 2 ways to unstage a file in git? - tidak pernah ada satu cara untuk melakukan apa pun di git. itulah keindahannya :)


303
2017-08-02 23:00



Cukup sederhana:

  • git rm --cached <file>  membuat git berhenti melacak file sepenuhnya (membiarkannya di filesystem, tidak seperti biasa git rm*)
  • git reset HEAD <file>  unstages setiap modifikasi yang dilakukan pada file sejak commit terakhir (tetapi tidak mengembalikannya di filesystem, bertentangan dengan apa yang mungkin disarankan oleh nama perintah **). File tetap berada di bawah kontrol revisi.

Jika file tidak dalam kendali revisi sebelumnya (yaitu Anda sedang membuka file yang baru saja Anda gunakan git added untuk pertama kalinya), maka kedua perintah itu memiliki efek yang sama, maka tampilan ini menjadi "dua cara melakukan sesuatu".

* Perlu diingat peringatan @DrewT menyebutkan dalam jawabannya, mengenai git rm --cached dari file itu sebelumnya berkomitmen ke repositori. Dalam konteks pertanyaan ini, dari sebuah file yang baru saja ditambahkan dan belum dilakukan, tidak ada yang perlu dikhawatirkan.

** Saya takut untuk waktu yang lama memalukan untuk menggunakan perintah git reset karena namanya - dan masih hari ini saya sering mencari sintaks untuk memastikan saya tidak mengacaukan. (memperbarui: Saya akhirnya meluangkan waktu untuk meringkas penggunaan git reset di halaman tldr, jadi sekarang saya memiliki model mental yang lebih baik tentang cara kerjanya, dan referensi cepat ketika saya melupakan beberapa detail.)


86
2017-10-17 21:16



Thread ini agak lama, tapi saya masih ingin menambahkan sedikit demonstrasi karena itu masih bukan masalah intuitif:

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(tanpa -q) memberi peringatan tentang file yang diubah dan kode keluarnya adalah 1 yang akan dianggap sebagai kesalahan dalam skrip.

Edit: git checkout HEAD to-be-modified to-be-removed juga berfungsi unstaging, tetapi menghapus perubahan sepenuhnya dari ruang kerja


35
2018-04-16 19:00



jika Anda tidak sengaja mementaskan file yang tidak ingin Anda komit, dan ingin memastikan Anda menyimpan perubahan, Anda juga dapat menggunakan:

git stash
git stash pop

ini melakukan reset ke HEAD dan menerapkan kembali perubahan Anda, memungkinkan Anda untuk mem-stage ulang file individual untuk dikomit. ini juga berguna jika Anda lupa membuat cabang fitur untuk menarik permintaan (git stash ; git checkout -b <feature> ; git stash pop).


27
2018-02-10 17:06



Kedua perintah ini memiliki beberapa perbedaan halus jika file yang dimaksud sudah di repo dan di bawah kontrol versi (sebelumnya berkomitmen dll):

  • git reset HEAD <file> unstages file dalam commit saat ini.
  • git rm --cached <file> akan melonggarkan file untuk commit di masa mendatang juga. Itu tidak digagalkan sampai ditambahkan lagi git add <file>.

Dan ada satu lagi perbedaan penting:

  • Setelah berlari git rm --cached <file> dan dorong cabang Anda ke remote, siapa pun yang menarik cabang Anda dari remote akan mendapatkan file SEBENARNYA dihapus dari folder mereka, meskipun di lokal Anda mengatur file hanya menjadi tidak terlacak (yaitu tidak dihapus secara fisik dari folder).

Perbedaan terakhir ini penting untuk proyek yang menyertakan file konfigurasi di mana setiap pengembang di tim memiliki konfigurasi yang berbeda (yaitu pengaturan basis url, ip atau port yang berbeda) jadi jika Anda menggunakan git rm --cached <file> siapa pun yang menarik cabang Anda harus secara manual membuat ulang konfigurasi, atau Anda dapat mengirimnya ke Anda dan mereka dapat mengeditnya kembali ke pengaturan ip mereka (dll.), karena hanya menghapus efek orang yang menarik cabang Anda dari remote .


14
2017-08-10 20:04



Katakan saja kamu stage seluruh direktori via git add <folder>, tetapi Anda ingin mengecualikan file dari daftar bertahap (yaitu daftar yang menghasilkan saat menjalankan git status) dan menjaga modifikasi dalam file yang dikecualikan (Anda sedang mengerjakan sesuatu dan itu belum siap untuk berkomitmen, tetapi Anda tidak ingin kehilangan pekerjaan Anda ...). Anda hanya bisa menggunakan:

git reset <file>

Saat Anda berlari git status, Anda akan melihat bahwa file apa pun (s) Anda reset adalah unstaged dan sisa file Anda added masih dalam staged daftar.


8
2017-08-28 16:08



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

(gunakan "git rm --cached ..." ke unstage)

  • git adalah sistem pointer

  • Anda belum memiliki komitmen untuk mengubah pointer Anda

  • satu-satunya cara untuk 'mengambil file dari bucket yang diarahkan ke' adalah untuk hapus file yang Anda beri tahu git untuk melihat perubahan

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 commit-m a

  • Anda berkomitmen, 'disimpan'

3

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

(gunakan "git reset HEAD ..." ke unstage)

  • Anda membuat komitmen dalam kode Anda saat ini
  • sekarang Anda dapat mereset penunjuk ke commit Anda 'kembali ke last save'

6
2017-09-08 16:26



Saya terkejut tidak ada yang menyebutkan git reflog (http://git-scm.com/docs/git-reflog):

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

Reflog adalah sejarah git yang tidak hanya melacak perubahan pada repo, tetapi juga melacak tindakan pengguna (misalnya, tarik, kasir ke cabang yang berbeda, dll) dan memungkinkan untuk membatalkan tindakan tersebut. Jadi, bukannya memunculkan file yang salah dipentaskan, di mana Anda dapat kembali ke titik di mana Anda tidak mementaskan file.

Ini mirip dengan git reset HEAD <file> tetapi dalam kasus-kasus tertentu mungkin lebih terperinci.

Maaf - tidak benar-benar menjawab pertanyaan Anda, tetapi hanya menunjuk cara lain untuk meng-unstage file yang saya gunakan cukup sering (saya untuk satu jawaban seperti oleh Ryan Stewart dan waldyrious sangat banyak.);) Saya harap itu membantu.


5
2018-02-10 12:06



Sepertinya saya itu git rm --cached <file> menghapus file dari indeks tanpa menghapusnya dari direktori tempat polos git rm <file> akan melakukan keduanya, sama seperti OS rm <file> akan menghapus file dari direktori tanpa menghapus versinya.


3