Bagaimana cara panggung hanya bagian dari file baru dengan git?

222

Saya suka git add --interactive . Sekarang bagian dari alur kerja harian saya.

Masalahnya tampaknya tidak berfungsi dengan file yang tidak dilacak. Yang ingin saya lakukan adalah melacak file baru, tetapi hanya menambahkan sebagian saja, yaitu beberapa bagian dari file baru ini belum siap untuk dipentaskan.

Sebagai contoh, dengan git add -i, saya dapat memilih opsi tambalan dan bahkan mengedit bakhil masing-masing untuk mem-tahap-kan bagian dari kode baru, meninggalkan komentar kode debug yang tidak dipentaskan. Saya suka bekerja dengan cara ini karena itu membuat jelas tempat mega patch yang saat ini saya kerjakan masih membutuhkan pekerjaan.

Sayangnya, saya sepertinya tidak dapat melakukan hal yang sama dengan file yang tidak terlacak. Entah saya menampilkan seluruh file, atau tidak sama sekali. Solusinya saya telah menggunakan adalah pementasan atau bahkan melakukan file baru ketika kosong, dan kemudian pementasan perubahan individu dengan cara biasa. Tetapi solusi ini terasa seperti hack kotor dan ketika saya lupa, atau berubah pikiran, itu menciptakan lebih banyak masalah daripada seharusnya.

Jadi pertanyaannya adalah: Bagaimana mem-stage hanya sebagian file baru, sehingga file baru ini dilacak tetapi membiarkan seluruh atau sebagian kontennya tidak di-stage?

augustin
sumber

Jawaban:

415

Wah, semua itu update-indexdan hash-objectbisnis tampaknya terlalu rumit. Bagaimana dengan ini sebagai gantinya:

git add -N new_file
git add -i

Dari git help add:

-N, --intent-to-add
    Record only the fact that the path will be added later.  An entry
    for the path is placed in the index with no content.  This is useful
    for, among other things, showing the unstaged content of such files
    with git diff and committing them with git commit -a.
Richard Hansen
sumber
9
++ 1! kredit jatuh tempo. Saya agak terlalu percaya bahwa saya tahu halaman-halaman ini sekarang ....</shame>
lihat
1
Ditemukan dengan baik. Seharusnya saya menggulir halaman manual sedikit lebih jauh. Mungkin aku harus mengembalikan lencana Git Pro.
dave1010
3
Bertanya-tanya mengapa git-gui tidak menggunakan ini secara internal untuk dapat membuat baris dari file baru.
Deiwin
6
Indah -Npenemuan, terima kasih! Meskipun aku lebih suka menggabungkannya dengan -pitu. gid add -N the_file& git add -p. Orang harus menambahkan itu -Njuga berfungsi dengan-A
Cyril CHAPON
@Deiwin - Anda bisa menambahkan [guitool] ke .gitconfig Anda untuk melakukan "git add -N $ FILENAME": [guitool "Tambah dengan niat"] cmd = "git add -N $ FILENAME" needsfile = yes noconsole = yes
Steve Folly
7

Cara termudah untuk melakukan ini (dan pementasan interaktif imho secara umum) adalah git gui. Itu datang dibundel dengan git dan harus bekerja pada hampir semua platform yang didukung oleh git.

Cukup jalankan git guidan gui akan terbuka yang memungkinkan pementasan dan pementasan bakhil dan bahkan satu baris file yang dilacak dan tidak terlacak.

Tangkapan layar Git Gui

Kronologis
sumber
Ini adalah jawaban yang kreatif dan terkadang sangat, sangat berguna.
Pablo Olmos de Aguilera C.
3
Hanya sebuah catatan yang tidak termasuk distribusi git git gui. Dalam Debian, misalnya, itu dalam paket terpisah yang disebut 'git-gui'.
cristoper
Telah mencari (tidak cukup keras) untuk fitur ini selama bertahun-tahun, ini adalah pengubah kehidupan
austinmarton
2
Bagi saya, pementasan satu baris file yang tidak terlacak git guitidak pernah berhasil. Bahkan, ini menonaktifkan opsi menu ini .
Deiwin
2
@Deiwin, saya benar-benar telah melewatkan ini dalam pertanyaan - tangkapan layar saya menunjukkan file yang sudah dilacak. Jika Anda ingin menggunakan git guifile baru, Anda harus menjalankannya git add -N new_filedulu - lihat jawaban Richard Hansen.
Kronik
6
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
git add --interactive newfile

Demo sederhana:

mkdir /tmp/demo
cd /tmp/demo
git init .

echo hello > newfile
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
  • Tips Jika Anda yakin gumpalan 'kosong' sudah ada di database objek git Anda, Anda bisa melakukan hardcode hash e69de29bb2d1d6434b8b29ae775ad8c2e48c5391. Saya tidak merekomendasikan melakukan itu_
  • Tips Jika Anda menggunakan Windows, Anda mungkin bisa menggunakan NUL:saja /dev/null. Kalau tidak, gunakan sesuatu sepertiecho -n '' | git hash-object --stdin -w

Sekarang indeks akan berisi newfilesebagai gumpalan kosong, dan gumpalan kosong telah dimasukkan ke dalam database objek jika belum ada:

$ find .git/objects/ -type f 
.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391

$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   newfile
#
# 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:   newfile
#

$ git diff
diff --git a/newfile b/newfile
index e69de29..ce01362 100644
--- a/newfile
+++ b/newfile
@@ -0,0 +1 @@
+hello

Ini harus tepat seperti yang Anda inginkan. Bolehkah saya juga merekomendasikan plugin pelarian vim untuk manajemen indeks yang sangat cerdas (lihat Better git add -p? )

lihat
sumber
1
Ini sepertinya bekerja dengan baik. Saya menyebutnya "stage-empty-file" karena ini agak rumit untuk diingat.
dave1010
@ dave1010: Senang bisa membantu! Ya saya berpikir tentang menambahkan alias, tapi saya tidak tahu bagaimana Anda berharap untuk menangani mis wildcard atau beberapa argumen nama file secara umum. Jadi saya memilih untuk tidak
melihat
2

Sunting: ini sepertinya tidak berfungsi sekarang. Saya yakin itu sebelumnya (pada git 1.7.1). Jika itu tidak berhasil, saya sarankan pementasan /dev/nullseperti yang disarankan di atas:

git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile

Jika Anda menggunakan Windows (tanpa /dev/null) maka Anda dapat menggantinya dengan path ke file kosong.

Jawaban asli

Kamu ingin

git add -p # (or --patch)

Ini menambahkan file yang tidak terlacak bagi saya. Dari halaman manual:

Pilih secara interaktif potongan patch antara indeks dan pohon kerja dan menambahkannya ke indeks. Ini memberi pengguna kesempatan untuk meninjau perbedaan sebelum menambahkan konten yang dimodifikasi ke indeks.

Ini secara efektif menjalankan add --interactive, tetapi mem-bypass menu perintah awal dan langsung melompat ke sub-perintah tambalan. Lihat "Mode interaktif" untuk detailnya.

dave1010
sumber
2
Betapapun menariknya, itu tidak berhasil untuk saya (git 1.7.4); git add -p newfiletidak bekerja sama sekali (efek nu) dangit add --interactive '[a] dd untracked' memiliki efek yang git add newfilememiliki; Sunting juga diperiksa dengan git 1.7.5.3; no dadu
sehe
Petunjuk yang bagus untuk Windows, menambahkan petunjuk untuk itu dalam jawaban saya. Thx
sehe
-2

Hanya untuk catatan kemungkinan lain: saya gunakan

git add -N file
git add -p file

Dan kemudian Anda dapat melakukan stage hunks, atau mengeditnya di tempat.

Pedro Adame Vergara
sumber
1
Jawaban ini mengatakan hal yang sama dengan jawaban yang diterima, yang berasal dari tahun 2011. Downvote.
Stanislav Pankevich
Jawaban yang diterima bergabung add -Ndengan add -i. Saya hanya menambahkan bahwa add -palih - alih add -ibekerja juga.
Pedro Adame Vergara