Git: Buat cabang dari perubahan unstaged / uncommitted pada master

991

Konteks: Saya sedang mengerjakan master menambahkan fitur sederhana. Setelah beberapa menit saya menyadari itu tidak begitu sederhana dan seharusnya lebih baik bekerja di cabang baru.

Ini selalu terjadi pada saya dan saya tidak tahu bagaimana cara beralih ke cabang lain dan mengambil semua perubahan yang tidak dikomit ini dengan saya meninggalkan cabang master bersih. Saya seharusnya git stash && git stash branch new_branchhanya mencapai itu, tetapi inilah yang saya dapatkan:

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

~/test $ echo "hello!" > testing 

~/test $ git status
# 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:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git stash
Saved working directory and index state WIP on master: 4402b8c testing
HEAD is now at 4402b8c testing

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

~/test $ git stash branch new_branch
Switched to a new branch 'new_branch'
# On branch new_branch
# 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:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (db1b9a3391a82d86c9fdd26dab095ba9b820e35b)

~/test $ git s
# On branch new_branch
# 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:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git checkout master
M   testing
Switched to branch 'master'

~/test $ git status
# 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:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

Apakah Anda tahu jika ada cara untuk mencapai ini?

knoopx
sumber
1
Meskipun ada solusi yang lebih sederhana untuk masalah Anda, dapatkah Anda menentukan dalam apa hasil yang Anda dapatkan berbeda dari yang Anda inginkan?
Gauthier
2
dengan melakukan jawaban di atas atau di bagian bawah, perubahan yang tidak dikomit berada di master dan cabang baru. Saya ingin mereka hanya di cabang baru, jadi saya bisa checkout master dan mengerjakan hal lain tanpa ada perubahan ini melayang
knoopx
1
lihat jawaban saya yang diedit. Anda perlu melakukan perubahan lokal di cabang baru jika Anda ingin checkout master bersih. Perubahan lokal hanya perbedaan antara KEPALA saat ini dan file Anda pada disk. Perubahan pada file lokal ini bukan versi, Anda harus memberitahu git untuk menyimpannya di suatu tempat jika Anda ingin mengambilnya nanti.
Gauthier

Jawaban:

1207

Tidak perlu disimpan.

git checkout -b new_branch_name

tidak menyentuh perubahan lokal Anda. Itu hanya membuat cabang dari KEPALA saat ini dan mengatur KEPALA di sana. Jadi saya kira itulah yang Anda inginkan.

--- Edit untuk menjelaskan hasil master checkout ---

Apakah Anda bingung karena checkout mastertidak membuang perubahan Anda?

Karena perubahan hanya bersifat lokal, git tidak ingin Anda kehilangannya terlalu mudah. Saat mengganti cabang, git tidak menimpa perubahan lokal Anda. Hasil dari Anda checkout masteradalah:

M   testing

, yang berarti file kerja Anda tidak bersih. git memang mengubah HEAD, tetapi tidak menimpa file lokal Anda. Itulah sebabnya status terakhir Anda masih menunjukkan perubahan lokal, meskipun Anda aktif master.

Jika Anda benar-benar ingin membuang perubahan lokal, Anda harus memaksa checkout -f.

git checkout master -f

Karena perubahan Anda tidak pernah dilakukan, Anda akan kehilangan mereka.

Cobalah untuk kembali ke cabang Anda, komit perubahan Anda, lalu checkout master lagi.

git checkout new_branch
git commit -a -m"edited"
git checkout master
git status

Anda harus mendapatkan Mpesan setelah checkout pertama, tetapi kemudian tidak lagi setelah checkout master, dan git statusseharusnya tidak menunjukkan file yang dimodifikasi.

--- Edit untuk menghapus kebingungan tentang direktori kerja (file lokal) ---

Sebagai jawaban atas komentar pertama Anda, perubahan lokal hanya ... baik, lokal. Git tidak menyimpannya secara otomatis, Anda harus mengatakannya untuk menyimpannya nanti. Jika Anda melakukan perubahan dan tidak secara eksplisit melakukan atau menyembunyikannya, git tidak akan membuat versinya. Jika Anda mengubah HEAD ( checkout master), perubahan lokal tidak ditimpa sejak tidak disimpan.

Gauthier
sumber
32
Yang membingungkan di sini adalah, halaman manual git itu menyatakan bahwa git checkout"Memperbarui file di pohon yang bekerja untuk mencocokkan versi dalam indeks atau pohon yang ditentukan.". Itu mengasumsikan perubahan Anda dalam sistem file Anda akan PERGI setelah itu. Tanpa ada kesempatan untuk mendapatkannya kembali. Bahkan jika Anda mengatakan mereka tidak mau, ini masih meninggalkan perasaan yang sangat buruk. Saya tidak percaya ini sama sekali . Entah dokumentasinya benar-benar buruk atau perilaku default git benar-benar berbahaya. Orang tidak harus percaya pada beberapa heuristik "automagic" untuk mendeteksi bahwa dalam hal ini Anda tidak ingin kehilangan perubahan Anda.
Evi1M4chine
16
Jika Anda memeriksa komit yang akan menimpa perubahan lokal Anda (jika riwayat antara komit saat ini dan komit target menyentuh file Anda yang dimodifikasi secara lokal), git menolak. Hanya jika checkouttidak bertentangan dengan perubahan lokal Anda, checkout berfungsi dan meninggalkan perubahan lokal sendiri. Saya mengerti perasaan buruk, halaman manual mungkin harus mengatakan "Pembaruan file yang tidak dimodifikasi di pohon kerja". Git tidak di sisi lain membuatnya terlalu mudah untuk kehilangan perubahan lokal. git checkoutbaik membiarkan perubahan lokal Anda sendiri, atau menolak jika ada konflik.
Gauthier
1
baik, bagaimana saya akan checkout ke cabang lain tanpa membawa perubahan lokal di sana?
ア レ ッ ク ス
5
@Alex git checkout <other_branch> -f. Anda akan kehilangan perubahan lokal tanpa peringatan.
Gauthier
2
@ Evi1M4chine Yang pertama. Dokumentasi adalah benar-benar buruk.
Qwertie
62

Mencoba:

git stash
git checkout -b new-branch
git stash apply
Grant Limberg
sumber
6
Apakah ini berbeda dengan hanya melakukan 'git checkout -b new-branch' dengan sendirinya?
Adrian Mouat
Saya kira itu bukan jawaban yang semula ditulis, tetapi saya bisa saja salah. Sayangnya karena keadaan kerja saya, saya telah menggunakan terpaksa selama beberapa tahun terakhir sehingga saya tidak bisa membuktikan keakuratannya sekarang.
Grant Limberg
6
Atau alih-alih dua langkah terakhir: cabang baru git simpanan cabang baru
rethab
1
simpanan git tidak lagi diperlukan
kory
Ketika Anda memiliki cabang yang sudah ada di mana Anda ingin meletakkan semua barang-barang Anda, simpanan masuk akal bagi saya: (Akhirnya git mengambil --semua; untuk mendapatkan cabang jauh di asal) git simpanan; git checkout <existing-branch>; git simpanan berlaku;
Paolof76
24

Dua hal yang dapat Anda lakukan:

git checkout -b sillyname
git commit -am "silly message"
git checkout - 

atau

git stash -u
git branch sillyname stash@{0}

( git checkout -<- tanda hubung adalah jalan pintas untuk cabang sebelumnya yang Anda kunjungi)

( git stash -u<- -ucara itu juga membutuhkan perubahan yang tidak dipentaskan)

Pylinux
sumber
7

Jika Anda menggunakan klien GitHub Windows (seperti saya) dan Anda berada dalam situasi membuat perubahan tanpa komitmen yang ingin Anda pindahkan ke cabang baru, Anda dapat dengan mudah "Membuat cabang baru" melalui klien GitHub. Ini akan beralih ke cabang yang baru dibuat dan menyimpan perubahan Anda.

masukkan deskripsi gambar di sini

Tod Birdsall
sumber
yang menyembunyikan perubahan sebelum membuat cabang baru sehingga tidak menyimpannya (versi 223 pada Mac OS)
Fernando Gallego
2

Jika Anda ingin perubahan yang tidak dikomit saat ini di cabang saat ini pindah ke cabang baru, gunakan perintah berikut untuk membuat cabang baru dan salin perubahan yang tidak dikomit secara otomatis.

git checkout -b branch_name

Ini akan membuat cabang baru dari cabang Anda saat ini (dengan anggapan sebagai master), salin perubahan yang tidak dikomit dan beralih ke cabang baru.

Komit perubahan Anda ke cabang baru.

git commit -m "First commit"

Karena, cabang baru dibuat, sebelum mendorongnya ke jarak jauh, Anda perlu mengatur upstream. Gunakan perintah di bawah ini untuk mengatur upstream dan mendorongnya ke jarak jauh.

git push --set-upstream origin feature/feature/NEWBRANCH

Setelah Anda menekan perintah ini, cabang baru akan dibuat di remote dan cabang lokal baru Anda akan didorong ke remote.

Sekarang, jika Anda ingin membuang perubahan yang tidak dikomit dari cabang master, gunakan:

git checkout master -f

Ini akan membuang perubahan lokal yang tidak dikomit saat checkout.

Maverick
sumber
Bagaimana jawaban ini berbeda dari yang diterima?
kometen
Meskipun ada beberapa tumpang tindih dengan jawaban yang diterima, ini memberikan panduan langkah demi langkah sederhana, dan juga mencakup operasi yang diperlukan untuk mendorong cabang baru dari jarak jauh. Sederhana, jelas, dan bermanfaat.
Kjartan
Jawaban ini jelas dan banyak membantu saya.
Vadim
0

Di klien GitHub terbaru untuk Windows , jika Anda memiliki perubahan yang tidak dikomit, dan pilih untuk membuat cabang baru.
Ini meminta Anda bagaimana menangani skenario yang tepat ini:

masukkan deskripsi gambar di sini

Hal yang sama berlaku jika Anda hanya mengganti cabang juga.

Jerry Dodge
sumber