Hanya komit sebagian file di Git

2765

Ketika saya membuat perubahan pada file di Git, bagaimana saya bisa melakukan hanya beberapa perubahan?

Misalnya, bagaimana saya bisa melakukan hanya 15 baris dari 30 baris yang telah diubah dalam file?

freddiefujiwara
sumber
3
stackoverflow.com/q/34609924/52074 terkait : jika Anda perlu membagi hunk menjadi hunks yang lebih kecil.
Trevor Boyd Smith
Ringkasan: dalam hal kemampuan: git gui= git add -e> git add -i -p; dalam hal kenyamanan: git gui> git add -i -p> git add -e. Jadi: pilih git guiketika Anda memiliki akses ke X. pilih git add -i -puntuk hal-hal sederhana dan ketika Anda tidak memiliki atau ingin menggunakan X. git add -euntuk pementasan kompleks tanpa X.
Penghe Geng

Jawaban:

3688

Anda dapat menggunakan git add --patch <filename>(atau -psingkatnya), dan git akan mulai memecah file Anda menjadi apa yang dianggapnya masuk akal "bakhil" (bagian dari file). Ini kemudian akan meminta Anda dengan pertanyaan ini:

Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]?

Berikut ini adalah deskripsi dari setiap opsi:

  • y panggung cowok ini untuk komit berikutnya
  • n jangan letakkan cowok ini untuk komit berikutnya
  • qberhenti; jangan menggelar rongsokan ini atau salah satu bakhil yang tersisa
  • a tahap ini cowok dan semua bakhil nanti dalam file
  • d jangan mem-stage hunk ini atau pun hunk yang ada di file
  • g pilih sebongkah untuk pergi ke
  • / mencari sebongkah yang cocok dengan regex yang diberikan
  • j biarkan bingkah ini bimbang, lihat bingkah bungkam berikutnya
  • J biarkan bingkah ini bimbang, lihat bingkah berikutnya
  • k biarkan bingkah ini bimbang, lihat bingkah batal sebelumnya
  • K biarkan bingkah ini ragu-ragu, lihat bingkah sebelumnya
  • s membagi hunk saat ini menjadi hunks yang lebih kecil
  • e secara manual mengedit bingkah saat ini
  • ? cetak bantuan cowok

Jika file tersebut belum ada di repositori, Anda dapat melakukannya terlebih dahulu git add -N <filename>. Setelah itu Anda bisa melanjutkan git add -p <filename>.

Setelah itu, Anda dapat menggunakan:

  • git diff --staged untuk memeriksa apakah Anda melakukan perubahan yang benar
  • git reset -p untuk unstage keliru menambahkan bakhil
  • git commit -v untuk melihat komit Anda saat Anda mengedit pesan komit.

Catatan ini jauh berbeda dari git format-patchperintah, yang tujuannya adalah untuk mengurai data komit ke dalam .patchfile.

Referensi untuk masa depan: Git Tools - Staging Interaktif

mac
sumber
83
Mungkin berguna untuk mencatat bahwa itu -p/--patchadalah jalan pintas ke tindakan tambalan di dalam -i/--interactiveperintah yang memulai mode Interaktif yang berguna .
tutuDajuju
5
> Apa yang terjadi jika file itu sudah dipentaskan? Ini hanya akan menampilkan perubahan yang tidak dipentaskan. Sama seperti git diffhalnya.
Eugen Konkov
3
Bagaimana saya bisa mengedit bingkah saat ini secara manual? Saya tidak tahu apa yang harus dilakukan setelah saya mengetik e.
Hunsu
23
Setelah menekan e, Anda dapat mengedit bongkahan secara manual dengan mengganti +atau -oleh#
veksen
1
ini bagus tapi sekarang bagaimana saya bisa mendorongnya? kalau saya git pushbilang sudah up to date. dan jika saya melakukannya git diffsaya melihat bakhil saya katakan n. jika git diff --stagedsaya melihat komit saya ingin mendorong. Dengan asumsi saya dapat mendorong komit, bagaimana cara menghapus bakhil yang saya katakan no?
chovy
250

Anda dapat menggunakan git add --interactiveatau , dan kemudian ( tidak ); lihat mode Interaktif di git-add manpage, atau cukup ikuti instruksi.git add -p <file>git commit git commit -a

Modern Git juga memiliki git commit --interactive(dan git commit --patch, yang merupakan jalan pintas ke opsi tambalan di komit interaktif).

Jika Anda lebih suka melakukannya dari GUI, Anda bisa menggunakan git-gui . Anda cukup menandai bongkahan yang ingin Anda sertakan dalam komit. Saya pribadi merasa lebih mudah daripada menggunakan git add -i. GUI Git lain, seperti QGit atau GitX, mungkin juga memiliki fungsi ini.

Jakub Narębski
sumber
1
Menariknya, windows.github.com memiliki dukungan untuk melakukan sebagian file tetapi tampaknya telah menjatuhkannya baru-baru ini ..
Juri
1
@ Juri Saya pikir dukungan untuk melakukan sebagian file kembali.
Ela782
@ Juri Sama-sama. Saya sebenarnya tidak pernah memperhatikan bahwa itu sudah ada di sana sebelumnya - saya melihatnya minggu lalu dan berpikir "oh, fitur baru yang luar biasa"! :-)
Ela782
1
Saat ini windows.github.com mengalihkan ke Desktop GitHub yang diganti merek yang lebih bagus daripada Git GUI dan mendukung sebagian komitmen ... tetapi tidak mendukung penandatanganan komitmen. Mendesah.
147

git gui menyediakan fungsionalitas ini di bawah tampilan diff. Cukup klik kanan baris yang Anda minati dan Anda akan melihat item menu "stage this to commit".

Ionuț G. Stan
sumber
13
untuk tambalan kompleks ini biasanya pendekatan tercepat bagi saya.
hochl
7
Ini adalah cara yang sangat efisien dan intuitif untuk menambahkan perubahan ke area pementasan secara halus. Juga beberapa baris dapat dipilih dan semua perubahan dalam pilihan itu akan ditambahkan.
Bersenang-senang
Perhatikan bahwa ini bukan gitk, tetapi disertakan dengan Git Bash untuk Windows; Anda harus memiliki entri menu mulai atau dapat memulainya dengan perintah git gui. Ada juga stage this hunkyang mungkin lebih bermanfaat daripada stage this line. Mungkin baru sejak jawaban ini dibuat 10 tahun yang lalu.
Chris
82

Saya percaya itu git add -e myfileadalah cara termudah (setidaknya preferensi saya) karena hanya membuka editor teks dan memungkinkan Anda memilih baris mana yang ingin Anda panggung dan baris mana yang tidak. Mengenai perintah pengeditan:

menambahkan konten:

Konten yang ditambahkan diwakili oleh baris yang dimulai dengan "+". Anda dapat mencegah pementasan saluran tambahan dengan menghapusnya.

konten yang dihapus:

Konten yang dihapus diwakili oleh baris yang dimulai dengan "-". Anda dapat mencegah pementasan penghapusan mereka dengan mengonversi "-" ke "" (spasi).

konten yang dimodifikasi:

Konten yang dimodifikasi diwakili oleh baris "-" (menghapus konten lama) diikuti oleh baris "+" (menambahkan konten pengganti). Anda dapat mencegah pementasan modifikasi dengan mengubah baris "-" menjadi "", dan menghapus baris "+". Berhati-hatilah bahwa memodifikasi hanya setengah dari pasangan cenderung menyebabkan perubahan membingungkan pada indeks.

Setiap detail tentang git addtersedia digit --help add

theFreedomBanana
sumber
7
Ini akan lebih berguna jika ada penjelasan yang jelas di suatu tempat tentang bagaimana sebenarnya memilih garis-garis tersebut (yaitu perintah yang sebenarnya untuk dimasukkan). Saya tidak dapat menemukannya di dokumentasi. Bisakah Anda menambahkan referensi?
Alex
4
Bagi mereka yang tidak suka opsi tulisan cepat, -eadalah --edit.
Kolyunya
2
@Alex Kutipan referensi yang ditambahkan oleh theFreedomBanana berasal dari bagian EDITING PATCHES digit --help add
Randall
8
Ini adalah satu-satunya jawaban (hanya membutuhkan git) yang memecahkan masalah menambah / menghapus garis bijak ketika Anda tidak dapat membuat bakhil lebih kecil dengan sdalam mode tambalan interaktif.
cdosborn
3
Mungkin bermanfaat untuk memahami bahwa perintah ini ( git add -e) * tidak * mengubah konten file pada disk. Itu hanya memindahkan bagian dari perubahan dari tidak bertahap ke panggung (indeks).
Penghe Geng
44

Jika Anda menggunakan vim, Anda mungkin ingin mencoba plugin yang bagus bernama fugitive .

Anda dapat melihat perbedaan file antara copy pekerjaan dan indeks dengan :Gdiff, dan kemudian menambahkan baris atau bakhil ke indeks menggunakan perintah vim diff klasik seperti dp. Simpan modifikasi dalam indeks dan komit dengan :Gcommit, dan Anda selesai.

Screencast pengantar yang sangat bagus di sini (lihat bagian 2 ).

François
sumber
Terima kasih banyak atas tautan ini. Persis sama dengan yang saya butuhkan. Terutama :diffget/:diffputdalam mode visual, di mana saya dapat memilih jalur tertentu, yang ingin saya reset / komit. Jadi, pastikan lagi: vim itu luar biasa.
goodniceweb
30

Saya akan sangat menyarankan menggunakan SourceTree dari Atlassian. (Ini gratis.) Itu membuat ini sepele. Anda dapat menampilkan setiap potongan kode atau setiap baris kode dengan cepat dan mudah.

masukkan deskripsi gambar di sini

Bob Stein
sumber
1
Saya setuju bahwa SourceTree adalah alat yang baik untuk tujuan ini, karena itu memberi Anda kontrol lebih baik daripada apa yang mungkin melalui baris perintah.
19
@cupcake Saya berpendapat sebaliknya, melihat bahwa SourceTree mungkin menggunakan perintah-perintah git executable, secara inheren akan selalu memungkinkan untuk melakukan tindakan yang sama (atau lebih) dengan baik melalui "command line".
tutuDajuju
2
Terlepas dari argumen berbutir halus saya akan sangat merekomendasikan SourceTree sebagai pementasan bakhil dan garis individual sangat mudah: i.imgur.com/85bNu4C.png
Mars Robertson
1
@tutuDajuju Dalam hal ini, saya tidak yakin itu benar. SourceTree memiliki kemampuan untuk memilih bagian mana yang akan di-stage demi baris . Anda tidak harus menggelar seluruh cowok; Anda dapat mengatur 2 garis di tengah sebongkah. Saya tidak tahu bagaimana itu mencapai itu. (Saat ini, saya sedang mencoba untuk mengatasi ketidakmampuan SourceTree untuk menggelar baris-baris tertentu untuk file yang tidak terlacak. Saya mendarat di sini untuk mencari solusi, hanya untuk menemukan bahwa git tampaknya tidak menawarkan kemampuan baris-demi-baris setidaknya tidak secara langsung.)
jpmc26
1
@Sun Anda dapat mengklik pada baris 50 dan menggeser + klik baris 100 lalu panggung. Anda dapat dengan mudah mengatur garis 50-100 di Sourcetree :)
ryan123
26

Perlu dicatat bahwa untuk digunakan git add --patchuntuk file baru, Anda harus terlebih dahulu menambahkan file ke indeks dengan git add --intent-to-add:

git add -N file
git add -p file
pengguna1338062
sumber
23

Ketika saya memiliki banyak perubahan, dan pada akhirnya akan membuat beberapa komit dari perubahan, maka saya ingin menyimpan titik awal saya sementara sebelum melakukan sesuatu.

Seperti ini:

$ git stash -u
Saved working directory and index state WIP on master: 47a1413 ...
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 1st commit"
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 2nd commit"
$ git stash pop

Jawaban Whymarrh adalah apa yang biasanya saya lakukan, kecuali kadang-kadang ada banyak perubahan dan saya dapat mengatakan bahwa saya mungkin membuat kesalahan saat melakukan hal-hal, dan saya ingin keadaan berkomitmen saya bisa mundur untuk umpan kedua.

jdsumsion
sumber
12

Jika Anda menggunakan emacs, lihatlah Magit , yang menyediakan antarmuka git untuk emacs. Ini mendukung pementasan bakhil (bagian file) dengan cukup baik.

Mark van Prapaskah
sumber
Saya sering tersandung perintah git yang ingin membuka editor, ketika saya menjalankannya dari jendela shell Mx. Apakah magit mencegat kegilaan itu, dan membuka hanya penyangga baru untuk itu? (tolong tidak ada petunjuk latar belakang-emacs-daemon; terima kasih tapi hidup ini terlalu singkat)
user2066657
Tidak, sejauh yang saya tahu itu tidak mencegat ini. Tapi jangan hanya mengambil kata-kata saya untuk itu karena (1) Saya jarang menggunakan jendela shell di Emacs, dan (2) Saya biasanya menggunakan emacsclient. Karena itu, jika emacsclient adalah pilihan bagi Anda, itu setidaknya mencegah jendela tambahan dengan emacs dibuka dan buffer "COMMIT_EDITMSG" dibuka di jendela Emacs saya yang ada.
Mark van Lent
10

Intellij IDEA (dan saya kira semua produk lain dari seri) telah membangun dukungan untuk sebagian komitmen sejak v2018.1

masukkan deskripsi gambar di sini

Holger Brandl
sumber
9

Bagi mereka yang menggunakan Git Extensions :

Di jendela Komit, pilih file yang ingin Anda komit sebagian, lalu pilih teks yang ingin Anda komit di panel kanan, lalu klik kanan pada pilihan dan pilih 'Tahap dipilih garis' dari menu konteks.

srgstm
sumber
2
Pintasan keyboard di Git Extensions untuk 'Stage selected lines' adalah s- sangat berguna untuk pementasan bagian file dengan cepat untuk komit.
Alchemistmatt
8

Sama seperti jawaban jdsumsion, Anda juga dapat menyembunyikan pekerjaan Anda saat ini tetapi kemudian menggunakan difftool seperti berbaur untuk menarik perubahan yang dipilih dari simpanan. Dengan begitu Anda bahkan dapat mengedit bakhil secara manual sangat mudah, yang agak menyebalkan ketika di git add -p:

$ git stash -u
$ git difftool -d -t meld stash
$ git commit -a -m "some message"
$ git stash pop

Menggunakan metode simpanan memberi Anda kesempatan untuk menguji, jika kode Anda masih berfungsi, sebelum Anda komit.

derhoch
sumber
ini bekerja dengan baik, tetapi jika Anda menggunakannya git commit --amend, tampaknya Anda tidak dapat menghapus simpanan setelahnya, atau apakah ada cara untuk melakukan ini?
Markus
7

Menambahkan pada jawaban sebelumnya, jika Anda lebih suka menggunakan baris perintah, memasukkan git add -e myfilememberi Anda pilihan untuk memilih baris demi baris apa yang ingin Anda komit karena perintah ini akan membuka editor dengan perbedaan, seperti:

masukkan deskripsi gambar di sini

Seperti yang Anda ketahui, baris yang memulai +adalah tambahan, baris yang dimulai dengan -penghapusan. Begitu:

  • Untuk tidak membuat tambahan, hapus saja baris itu.
  • Untuk tidak melakukan penghapusan, ganti saja -dengan spasi .

Inilah yang git add -hdikatakan tentang menambahkan file dengan cara ini (menambal file):

konten yang ditambahkan Menambahkan konten diwakili oleh baris yang dimulai dengan "+". Anda dapat mencegah pementasan saluran tambahan dengan menghapusnya.

konten yang dihapus: Konten yang dihapus diwakili oleh baris yang dimulai dengan "-". Anda dapat mencegah pementasan penghapusan mereka dengan mengonversi "-" ke "" (spasi).

konten yang dimodifikasi: Konten yang dimodifikasi diwakili oleh baris "-" (menghapus konten lama) diikuti oleh baris "+" (menambahkan konten pengganti). Anda dapat mencegah pementasan modifikasi dengan mengubah baris "-" menjadi "", dan menghapus baris "+". Berhati-hatilah bahwa memodifikasi hanya setengah dari pasangan cenderung menyebabkan perubahan membingungkan pada indeks.

Perhatian: jangan mengubah konten file, ini bukan tempat yang baik untuk melakukannya. Cukup ganti operator dari baris yang dihapus atau ditambahkan.

Beto Aveiga
sumber
Apa jawaban sebelumnya? Jawaban disimpan berdasarkan jumlah poin yang mereka miliki. Jadi jawaban Anda ada di tempat yang berbeda sekarang daripada saat Anda menulisnya dibandingkan dengan jawaban lain.
KulaGGin
Saya percaya jawaban yang dirujuk adalah dari @theFreedomBanana
K. Symbol
6

Plugin vim-gitgutter dapat membuat stage bakhun tanpa meninggalkan vim editor menggunakan

:GitGutterStageHunk

Selain itu, ia menyediakan fitur keren lainnya seperti kolom tanda berbeda seperti pada beberapa IDE modern

Jika hanya sebagian dari sebongkah yang harus dipentaskan vim-buron

:Gdiff

memungkinkan pemilihan rentang visual lalu :'<,'>diffputatau :'<,'>diffgetuntuk tahap / mengembalikan perubahan garis individual.

c0ffeeartc
sumber
4

Dengan TortoiseGit:

klik kanan pada file dan gunakan Context Menu → Restore after commit. Ini akan membuat salinan file apa adanya. Kemudian Anda dapat mengedit file, misalnya di TortoiseGitMerge dan membatalkan semua perubahan yang tidak ingin Anda lakukan. Setelah menyimpan perubahan itu, Anda dapat mengkomit file.

Fr0sT
sumber
4

Sudah 10 tahun sejak pertanyaan ini diajukan. Dan saya berharap jawaban ini bermanfaat bagi seseorang. Seperti disebutkan dalam jawaban di sini , di mana GUI bukan pilihan, ekstensi crecord Andrew Shadura membantu membawa jendela ncurses di mana kita dapat memilih jalur yang akan dikomit.

Siapkan ekstensi sebagai berikut:

git clone https://github.com/andrewshadura/git-crecord
cd git-crecord
./setup.py install
ln -s $PWD/git-crecord ~/.local/bin/git-crecord

cd ke git repo Anda dan aktifkan sebagai berikut:

git crecord

Ini akan memunculkan antarmuka ncurses yang dapat digunakan seperti yang ditunjukkan di bawah ini. Menekan tombol berikut di jendela ncurses akan melakukan tindakan tertentu:

f       hunk toggle fold (arrow keys can also be used)
space   toggle hunk selection
a       toggle commit or amend
c       confirm and open commit window

Screencast menunjukkan penggunaan sampelContoh

Arun
sumber
3

Untuk pengguna Atom , paket github termasuk pementasan interaktif, dengan gaya git gui. Untuk cara pintas lihat dokumentasi paket .

Menggunakan Atom memungkinkan bekerja dengan tema yang memiliki latar belakang gelap (secara default, git guimemiliki latar belakang putih).

Ioannis Filippidis
sumber
2

git-meld-index - mengutip dari situs web:

git-meld-index menjalankan bld - atau gt difftool lainnya (kdiff3, difuse, dll.) - untuk memungkinkan Anda untuk secara interaktif melakukan perubahan pada indeks git (juga dikenal sebagai area pementasan git).

Ini mirip dengan fungsi git add -p, dan git add --interactive. Dalam beberapa kasus, berbaur lebih mudah / lebih cepat untuk digunakan daripada git add -p. Itu karena berbaur memungkinkan Anda, misalnya, untuk:

  • lihat lebih banyak konteks
  • lihat perbedaan intra-line
  • edit dengan tangan dan lihat pembaruan berbeda 'langsung' (diperbarui setelah setiap penekanan tombol)
  • arahkan ke suatu perubahan tanpa mengatakan 'n' ke setiap perubahan yang ingin Anda lewati

Pemakaian

Di repositori git, jalankan:

git meld-index

Anda akan melihat meld (atau difftool git yang dikonfigurasi) muncul dengan:

KIRI : direktori sementara meneruskan file yang disalin dari pohon kerja Anda

KANAN : direktori sementara dengan isi indeks. Ini juga termasuk file yang belum ada dalam indeks tetapi dimodifikasi atau tidak dilacak dalam copy pekerjaan - dalam hal ini Anda akan melihat konten file dari HEAD.

Edit indeks (sisi kanan) sampai bahagia. Ingatlah untuk menabung saat dibutuhkan.

Setelah selesai, tutup berbaur, dan git-meld-indeks akan memperbarui indeks agar sesuai dengan isi direktori sementara di sisi kanan berbaur yang baru saja Anda edit.

Langshan Croad
sumber
2

Jika ada di Windowsplatform, menurut saya git guialat yang sangat bagus untuk stage/ commitbeberapa baris dari unstagedfile

1. Cowok bijaksana:

  • Pilih file dari unstagged Changesbagian
  • Klik kanan potongan kode yang perlu dipentaskan
  • Pilih Stage Hunk for commit

2. Garis bijak:

  • Pilih file dari unstagged Changesbagian
  • Pilih garis / garis yang akan dipentaskan
  • Klik kanan dan pilih Stage Lines for commit

3. Jika Anda ingin mem-stage file lengkap kecuali beberapa baris:

  • Pilih file dari unstagged Changesbagian
  • tekan Ctrl+T (Stage file to commit)
  • File yang dipilih sekarang pindah ke Staged ChangesBagian
  • Pilih garis / garis yang akan dipentaskan
  • Klik kanan dan pilih UnStage Lines for commit
Anvesh Yalamarthy
sumber
1

Seperti yang ditunjukkan oleh satu jawaban di atas, Anda dapat menggunakannya git add --patch filename.txt

atau bentuk pendek git add -p filename.txt

... tetapi untuk file yang sudah ada di repositori Anda, ada, di s jauh lebih baik menggunakan flag --patch pada perintah commit secara langsung (jika Anda menggunakan versi git yang cukup baru): git commit --patch filename.txt

... atau, sekali lagi, formulir pendek git commit -p filename.txt

... dan kemudian menggunakan kunci yang disebutkan, (y / n dll), untuk memilih baris untuk dimasukkan dalam komit.

Samuel Lampa
sumber
Apa yang memberi Anda " git add -p filename.txt" selain sedikit ruang untuk kesalahan? Jika Anda mengacaukan perubahan sebagian file, membatalkan suatu penambahan lebih baik daripada membatalkan suatu komit.
CTMacUser
Saya tidak tahu mengapa, tetapi ketika saya mengatakan 'n' baris dimasukkan .... dan ketika saya mengatakan 'y' pada cowok ke-2, itu juga termasuk.
chovy
1

git-cola adalah GUI yang hebat dan juga memiliki fitur bawaan. Cukup pilih garis ke panggung dan tekan S. Jika tidak ada pilihan yang dibuat, bagian lengkapnya dipentaskan.

AndiDog
sumber