Menyimpan hanya perubahan un-staged di Git

229

Saya ingin melakukan alur kerja berikut:

  1. Tambahkan perubahan ke panggung.
  2. Simpan semua perubahan lain yang tidak dipentaskan.
  3. Lakukan beberapa hal dengan hal-hal di panggung (yaitu membangun, menjalankan tes, dll)
  4. Terapkan simpanan.

Apakah ada cara untuk melakukan langkah 2?

Contoh

 echo "123" > foo
 git add foo # Assumes this is a git directory
 echo "456" >> foo
 git stash
 cat foo # Should yield 123
Unapiedra
sumber
Mengapa tidak melakukan perubahan setelah mementaskannya?
Shizzmo
3
IIRC --keepindex melakukan hal itu
lihat
4
Karena jika, katakanlah, build gagal saya tidak ingin memiliki komitmen ini. Saya tahu saya bisa menghapus komit tapi saya ingin melakukan ini tanpa komit jika memungkinkan.
Unapiedra
Terima kasih. Saya dapat mengkonfirmasi ini berfungsi. Wah, saya melihat manual di linux.die.net/man/1/git-stash yang kedaluwarsa. man git stashjauh lebih baik.
Unapiedra
itu --keep-index, fwiw.
jaf0

Jawaban:

288

git stash savememiliki opsi --keep-indexyang melakukan apa yang Anda butuhkan.

Jadi, lari git stash save --keep-index.

vhallac
sumber
9
Benar. Saya tetap menggunakan savedengan git stash. Mungkin itu adalah programmer di saya bersikeras menghormati simetri dengan apply / pop. :)
vhallac
104
Catatan: ini masih menyimpan semua perubahan Anda; satu-satunya perbedaan dari reguler git stash saveadalah ia meninggalkan perubahan yang sudah dipentaskan dalam copy pekerjaan Anda juga. Dalam alur kerja di atas ini akan berfungsi dengan baik karena Anda hanya menerapkan simpanan di atas salinan lokal yang sudah memiliki setengah dari perubahan simpanan (yang git cukup pintar untuk diabaikan). Tetapi jika Anda mengedit kode sebelum menerapkan kembali simpanan, Anda berpotensi melihat konflik penggabungan saat Anda mendaftar. Fyi.
peterflynn
2
@ sitpete Itu telah menggigit saya berkali-kali. Saya benar-benar berharap ada cara agar git hanya menyembunyikan hal-hal yang tidak Anda pertahankan ... Saya sering melakukan hal-hal, kemudian melakukan simpanan git penuh, mengetahui bahwa saya bisa git commit --ammendjika ada masalah dalam apa yang saya lakukan.
rjmunro
1
--amend(alih-alih --ammend)
Rhubbarb
19
Solusi ini tidak berfungsi untuk saya karena masalah yang dijelaskan oleh peterflynn. Ini bukan jawaban yang baik untuk pertanyaan karena masih menyembunyikan perubahan bertahap. Adakah yang punya solusi yang lebih baik?
user643011
43

Ini dapat dilakukan dalam 3 langkah: menyimpan perubahan bertahap, menyimpan semuanya, mengembalikan indeks dengan perubahan bertahap. Yang pada dasarnya adalah:

git commit -m 'Save index'
git stash push -u -m 'Unstaged changes and untracked files'
git reset --soft HEAD^

Ini akan melakukan apa yang Anda inginkan.

alesguzik
sumber
3
Catatan: -ujuga menyimpan file yang tidak terlacak.
ma11hew28
Pendekatan ini pada dasarnya menduplikasi apa yang git stash save --keep-indexdilakukan dengan lebih banyak pekerjaan. Saya tidak melihat keuntungan apa pun.
Inigo
1
@vas Tidak, pendekatannya tidak menduplikasi itu. Lihat komentar peterflynn untuk jawaban yang diterima.
Alexander Klauer
28
git stash save --keep-index

Juga, Re:

Mengapa tidak melakukan perubahan setelah mementaskannya? - Shin

A: Karena Anda harus selalu checkin kode yang diuji :) Itu berarti, Anda harus menjalankan tes dengan hanya perubahan yang akan Anda lakukan

Semua ini terlepas dari fakta bahwa tentu saja, sebagai programmer yang berpengalaman, Anda memiliki keinginan bawaan untuk menguji dan meninjau hanya perubahan-perubahan itu - hanya sebagian bercanda

lihat
sumber
14

Dengan git version 2.7.4Anda dapat melakukan:

git stash save --patch

The gitakan meminta Anda untuk menambahkan atau tidak perubahan dalam simpanan.
Dan Anda hanya menjawab yataun

Anda dapat mengembalikan direktori kerja seperti biasa:

git stash pop

atau, jika Anda ingin menyimpan perubahan yang disimpan di simpanan:

git stash apply
Eugen Konkov
sumber
Ini luar biasa. Agak padat karya, tapi setidaknya Anda bisa melewati dan menambahkan seluruh file.
Dustin Oprea
5

Memperluas jawaban sebelumnya, saya terkadang memiliki serangkaian perubahan yang rumit, tetapi ingin melakukan perubahan yang terpisah terlebih dahulu. Misalnya, saya mungkin telah melihat bug atau kode yang salah yang ingin saya perbaiki sebelum perubahan bertahap saya. Salah satu rute yang mungkin ditempuh adalah:

sembunyikan dulu semuanya, tapi biarkan perubahan bertahap

$ git simpanan simpan --keep-index [--include-untracked]

sekarang menyimpan perubahan bertahap juga

$ git menyimpan simpanan

buat perubahan untuk perbaikan; dan uji; komit pada mereka:

$ git tambahkan [--interaktif] [--patch]

$ git commit -m "fix ..."

sekarang kembalikan perubahan yang dipentaskan sebelumnya:

$ git simpanan pop

menyelesaikan konflik, dan perhatikan bahwa jika ada konflik, git akan menerapkan tetapi tidak menjatuhkan entri simpanan teratas itu.

(... Kemudian komit perubahan bertahap, dan kembalikan simpanan semua perubahan lainnya, dan lanjutkan ...)

Rhubbarb
sumber
4

Untuk menambahkan file tidak bertanda (tidak ditambahkan untuk melakukan) ke simpanan, jalankan perintah berikut:

git stash -k

Kemudian Anda dapat melakukan file yang dipentaskan. Setelah itu Anda bisa mendapatkan kembali file simpanan terakhir menggunakan perintah:

git stash pop
srth12
sumber
4

Menyimpan hanya pohon kerja (perubahan yang tidak dipentaskan) di Git lebih sulit dari yang seharusnya. Jawaban yang diterima menyembunyikan perubahan yang tidak dipentaskan , tetapi juga menyembunyikan perubahan yang dipentaskan (dan membiarkannya juga dipentaskan), yang jarang seperti yang Anda inginkan.

Alias ​​ini berfungsi dengan baik:

stash-working = "!f() { \
  git commit --quiet -m \"temp for stash-working\" && \
  git stash push \"$@\" && \
  git reset --quiet --soft HEAD~1; }; f"

Itu melakukan perubahan bertahap, membuat simpanan dari perubahan yang tersisa (dan memungkinkan argumen tambahan seperti --include-untrackeddan --messagediteruskan sebagai argumen alias), dan kemudian mengatur ulang komit sementara untuk mendapatkan kembali perubahan bertahap.

Ini mirip dengan jawaban @Simon Knapp , tetapi dengan beberapa perbedaan kecil - ini digunakan --quietpada tindakan sementara yang diambil, dan menerima sejumlah parameter untuk simpanan push, daripada mengkode-m , dan menambahkan --softke final reset sehingga indeks tetap seperti semula.

Untuk masalah sebaliknya menyimpan hanya perubahan bertahap (alias stash-index) lihat jawaban ini .

Raman
sumber
2

Kiat lain, terkait dengan pertanyaan:

Ketika Anda secara efektif menyimpan perubahan yang tidak bertahap menggunakan

simpanan $ git simpan --keep-index

Anda mungkin ingin memberikan simpanan pesan, sehingga ketika Anda melakukan a git stash list itu lebih jelas apa yang telah Anda simpanan sebelumnya, terutama jika Anda mengikuti operasi simpanan dengan menyimpan lebih lanjut. Sebagai contoh

simpanan $ git save --keep-index "perubahan belum dipentaskan"

(walaupun sebenarnya itu memang berisi semua perubahan seperti dicatat dalam jawaban lain).

Misalnya, hal di atas dapat segera diikuti oleh:

$ git simpanan simpan "perubahan bertahap untuk fitur X"

Namun berhati-hatilah bahwa Anda tidak dapat menggunakannya

$ git simpanan berlaku "simpanan @ {1}" ### ✘ tidak cukup melakukan apa yang Anda inginkan

untuk mengembalikan hanya perubahan yang tidak dipentaskan.

Rhubbarb
sumber
2

Git tidak memiliki perintah yang menyembunyikan hanya perubahan yang tidak dipentaskan.

Git tidak, bagaimanapun, membiarkan Anda menentukan file mana yang ingin Anda simpanan.

git stash push --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb

Jika Anda hanya ingin menyembunyikan perubahan spesifik pada file-file itu, tambahkan --patchopsi.

git stash push --patch --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb

The --include-untrackedpilihan memungkinkan Anda menyimpan file yang tidak terlacak.

git stash push --include-untracked --message 'Untracked files' -- app/controllers/widgets_controller.rb test/controllers/widgets_controller_test.rb

Jalankan git help stash(atau man git-stash) untuk info lebih lanjut.

Catatan: Jika perubahan yang tidak Anda lakukan agak disogan, jawaban @ alesguzik mungkin lebih mudah.

ma11hew28
sumber
0

Bentuk modern dari perintah itu adalah git stash push [--] [<pathspec>...], karena Git 2.16+ ( git stash savesudah usang )

Anda dapat menggabungkannya dengan formulir wildcard, misalnya:

git stash push --all --keep-index ':(glob)**/*.testextension' 

Tapi itu tidak bekerja dengan baik dengan Git untuk Windows, sampai Git 2.22 (Q2 2019), lihat edisi 2037 , mengingat git stashtelah diimplementasikan kembali di C (bukan skrip shell)

Lihat komit 7db9302 (11 Mar 2019) oleh Thomas Gummerer ( tgummerer) .
Lihat komit 1366c78 , komit 7b556aa (07 Mar 2019) oleh Johannes Schindelin ( dscho) .
(Digabung oleh Junio ​​C Hamano - gitster- dalam commit 0ba1ba4 , 22 Apr 2019)

built-in stash: handle :(glob)pathspecs lagi

Saat melewati daftar pathspec ke, katakan, git add kita perlu berhati-hati untuk menggunakan bentuk asli, bukan bentuk parsed dari pathspec.

Ini membuat perbedaan misalnya saat menelepon

git stash -- ':(glob)**/*.txt'

di mana bentuk asli termasuk :(glob)awalan sedangkan bentuk parsing tidak.

Namun, dalam bawaan git stash, kami melewati formulir yang diuraikan (mis. Salah), dan git addakan gagal dengan pesan kesalahan:

fatal: pathspec '**/*.txt' did not match any files

pada tahap di mana git stashmenjatuhkan perubahan dari worktree, bahkan jika refs/stashsebenarnya telah berhasil diperbarui.

VONC
sumber
0

Saya menggunakan alias, yang menerima string untuk digunakan sebagai pesan ke entri simpanan.

mystash = "!f() { git commit -m hold && git stash push -m \"$1\" && git reset HEAD^; }; f"

Yang:

  • melakukan semua yang ada dalam indeks,
  • menyembunyikan apa yang diubah di pohon kerja (tentu saja bisa menambah -uatau -a),
  • me-reset komit terakhir kembali ke percobaan kerja (mungkin ingin digunakan --softuntuk menyimpannya dalam indeks).
Simon Knapp
sumber