Bagaimana cara membalikkan simpanan simpanan?

233

Saya memiliki patch kecil yang disimpan di simpanan git saya. Saya sudah menerapkannya ke copy pekerjaan saya menggunakan git stash apply. Sekarang, saya ingin mendukung perubahan itu dengan menerapkan patch secara terbalik (seperti apa yang git revertakan dilakukan selain melawan simpanan).

Adakah yang tahu bagaimana melakukan ini?

Klarifikasi: Ada perubahan lain dalam copy pekerjaan saya. Kasus khusus saya sulit untuk dijelaskan tetapi Anda dapat membayangkan beberapa kode debugging atau eksperimental yang ada di simpanan. Sekarang sudah tercampur dalam copy pekerjaan saya dengan beberapa perubahan lain dan saya ingin melihat efeknya dengan dan tanpa perubahan dari simpanan.

Ini tidak terlihat seperti simpanan yang mendukung ini saat ini, tetapi git stash apply --reversefitur yang bagus.

Pat Notz
sumber
1
Tidak bisakah hanya membuat tambalan yang dibalik dengan membedakan antara revisi saat ini dan sebelumnya? Dan kemudian menerapkannya?
ralphtheninja
Apakah ada perubahan di pohon kerja selain simpanan yang diterapkan?
Greg Bacon
Menambahkan ini di sini, ... seharusnya menjadi FAQ bukan pertanyaan ... stackoverflow.com/questions/59973103/…
Don Thomas Boyle

Jawaban:

188

Menurut halaman git-simpanan , "Sebuah simpanan diwakili sebagai komit yang pohonnya mencatat status direktori kerja, dan orangtua pertamanya adalah komit HEADketika simpanan dibuat," dan git stash show -pmemberi kami "perubahan yang dicatat dalam simpanan sebagai perbedaan antara status simpanan dan induk aslinya.

Untuk menjaga perubahan Anda yang lain tetap utuh, gunakan git stash show -p | patch --reverseseperti berikut ini:

$ git init
Initialized empty Git repository in /tmp/repo/.git/

$ echo Hello, world >messages

$ git add messages

$ git commit -am 'Initial commit'
[master (root-commit)]: created 1ff2478: "Initial commit"
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 messages

$ echo Hello again >>messages

$ git stash

$ git status
# On branch master
nothing to commit (working directory clean)

$ git stash apply
# On branch master
# 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:   messages
#
no changes added to commit (use "git add" and/or "git commit -a")

$ echo Howdy all >>messages

$ git diff
diff --git a/messages b/messages
index a5c1966..eade523 100644
--- a/messages
+++ b/messages
@@ -1 +1,3 @@
 Hello, world
+Hello again
+Howdy all

$ git stash show -p | patch --reverse
patching file messages
Hunk #1 succeeded at 1 with fuzz 1.

$ git diff
diff --git a/messages b/messages
index a5c1966..364fc91 100644
--- a/messages
+++ b/messages
@@ -1 +1,2 @@
 Hello, world
+Howdy all

Edit:

Perbaikan ringan untuk ini adalah untuk digunakan git applysebagai pengganti tambalan:

git stash show -p | git apply --reverse

Atau, Anda juga dapat menggunakan git apply -Rsebagai singkatan untuk git apply --reverse.

Saya telah menemukan ini sangat berguna belakangan ini ...

Greg Bacon
sumber
2
Keren terima kasih. Sepertinya ini mungkin fitur yang bagus untuk simpanan.
Pat Notz
5
Ya, git apply -Rini merupakan peningkatan, setidaknya bagi saya di kotak windows saya dengan git bash karena patch --reversememiliki masalah untuk menemukan file untuk ditambal (tidak ada petunjuk nyata mengapa alternatifnya bekerja). +1 dan penjelasan yang baik
hakre
bukankah lebih baik menambahkan --indexseperti ini saja git stash show -p | git apply --reverse --index. Karena Anda tidak lagi perlu menambahkan indeks perubahan yang dikembalikan kembali.
theUnknown777
3
@ Greg Bacon, hey, saya sudah mencoba untuk pergi melalui script yang Anda digariskan, tetapi patch gagal ketika aku berlari git stash show -p | git apply -R -vdengan pesan: Checking patch messages... error: while searching for: Hello, world Hello again error: patch failed: messages:1. Apakah Anda tahu apa yang salah?
Max Koretskyi
5
Saya mendapatkan kesalahan: patch gagal: /src/filename.java:46 kesalahan: src / filename.java patch tidak berlaku
Tim Boland
83

git stash[save]membawa status direktori kerja Anda, dan status indeks Anda, dan menyimpannya, menetapkan indeks dan area kerja ke HEADversi.

git stash applymengembalikan perubahan itu, jadi git reset --hardakan menghapusnya lagi.

git stash popmengembalikan perubahan tersebut dan menghapus perubahan simpanan teratas, sehingga git stash [save]akan kembali ke keadaan sebelumnya (pra-pop) dalam kasus ini.

Jakub Narębski
sumber
82
git checkout -f

akan menghapus semua perubahan yang tidak dilakukan.

salman
sumber
4
terima kasih, Anda membantu saya dari perubahan bertahap yang tidak mengecewakan.
Fa.Shapouri
1
Ini jauh lebih sederhana
Mark A
Ini luar biasa!
Kiran Sk
22

Halaman manual V1 git memiliki referensi tentang membatalkan penerapan simpanan. Kutipan di bawah ini.

Halaman manual V2 git yang lebih baru tidak termasuk referensi untuk membatalkan penerapan simpanan tetapi di bawah ini masih berfungsi dengan baik

Membatalkan penerapan Stash Dalam beberapa skenario kasus penggunaan, Anda mungkin ingin menerapkan perubahan simpanan, melakukan beberapa pekerjaan, tetapi kemudian membatalkan penerapan perubahan yang awalnya berasal dari simpanan. Git tidak menyediakan simpanan membatalkan perintah, tetapi dimungkinkan untuk mencapai efek dengan hanya mengambil tambalan yang terkait dengan simpanan dan menerapkannya secara terbalik:

$ git stash show -p stash@{0} | git apply -R

Sekali lagi, jika Anda tidak menentukan simpanan, Git mengasumsikan simpanan terbaru:

$ git stash show -p | git apply -R

Anda mungkin ingin membuat alias dan menambahkan perintah simpanan-tidak-berlaku untuk Git Anda. Sebagai contoh:

$ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
$ git stash apply
$ #... work work work
$ git stash-unapply
Choco Smith
sumber
1
Untuk alasan apa pun bagian yang membantu ini yang Anda tautkan "Membatalkan penerapan Stash" dihapus dari versi ke-2 - Versi terbaru saat ini adalah 2.1.146, 2019-04-15- dari buku ini V2- Git Tools - Stashing and Cleaning . Bisa jadi karena penulis berpikir ada cara yang lebih baik untuk melakukan ini yang sepertinya tidak bisa saya temukan.
Nad Alaba
@NadAlaba, terima kasih atas bantuannya, telah memperbarui jawaban untuk mencatat perbedaan antara v1 dan v2 ... anehnya para penulis git menghapus bagian tentang membatalkan penerapan simpanan
Choco Smith
13

Ini sudah lama berakhir, tetapi jika saya menafsirkan masalah dengan benar saya telah menemukan solusi sederhana, perhatikan, ini adalah penjelasan dalam terminologi saya sendiri:

git stash [save] akan menyimpan perubahan saat ini dan mengatur cabang Anda saat ini ke "kondisi bersih"

git stash list memberikan sesuatu seperti: stash@{0}: On develop: saved testing-stuff

git apply stash@{0}akan mengatur cabang saat ini seperti sebelumnya stash [save]

git checkout .Akan menetapkan cabang saat ini sebagai setelah stash [save]

Kode yang disimpan dalam simpanan tidak hilang, dapat ditemukan git apply stash@{0}kembali.

Bagaimanapun, ini berhasil untuk saya!

Slim Sim
sumber
Hanya untuk memastikan, saya menerapkan yang git stash apply --reversepertama dan kemudian kembali git stash apply stash@{x}seperti yang Anda sebutkan. Bekerja tanpa masalah.
Carlos Garcia
3

Bagaimana cara membalikkan simpanan simpanan?

Terlepas dari apa yang disebutkan orang lain, cara termudah adalah yang pertama dilakukan

git reset HEAD

dan kemudian checkout semua perubahan lokal

git checkout . 
Achal
sumber
Sejauh ini, ini adalah cara termudah selama Anda sama sekali tidak memiliki pekerjaan lokal yang ingin Anda selamatkan. Jika Anda menerapkan simpanan yang salah ke cabang atau menekan konflik gabungan yang tidak ingin Anda selesaikan, ini adalah cara cepat dan mudah untuk membatalkannya dengan sepenuhnya mengembalikan set kerja Anda ke komit terbaru cabang Anda.
Shadoninja
2

Selain jawaban @Greg Bacon, seandainya file biner ditambahkan ke indeks dan merupakan bagian dari simpanan menggunakan

git stash show -p | git apply --reverse

dapat menghasilkan

error: cannot apply binary patch to '<YOUR_NEW_FILE>' without full index line
error: <YOUR_NEW_FILE>: patch does not apply

Menambahkan --binarymenyelesaikan masalah, tapi sayangnya belum menemukan alasannya.

 git stash show -p --binary | git apply --reverse
MHosafy
sumber
1

Anda dapat mengikuti gambar yang saya bagikan untuk melepaskan jika Anda secara tidak sengaja mengetuk simpanan.

Amanpreet Singh
sumber
0

Ini merupakan tambahan untuk jawaban di atas tetapi menambahkan pencarian untuk simpanan git berdasarkan pesan sebagai nomor simpanan dapat berubah ketika simpanan baru disimpan. Saya telah menulis beberapa fungsi bash:

apply(){
  if [ "$1" ]; then
    git stash apply `git stash list | grep -oPm1 "(.*)(?=:.*:.*$1.*)"`
  fi
}
remove(){
  if [ "$1" ]; then
    git stash show -p `git stash list | grep -oPm1 "(.*)(?=:.*:.*$1.*)"` | git apply -R
    git status
  fi
}
  1. Buat simpanan dengan nama (pesan) $ git stash save "my stash"
  2. Untuk bernama appply $ apply "my stash"
  3. Untuk menghapus simpanan bernama $ remove "my stash"
seumur hidup
sumber