Bagaimana cara menggabungkan perubahan lokal saya yang tidak dikomit ke cabang Git lainnya?

621

Bagaimana saya bisa melakukan hal berikut di Git?

Cabang saya saat ini adalah branch1 dan saya telah membuat beberapa perubahan lokal. Namun, saya sekarang menyadari bahwa saya sebenarnya bermaksud menerapkan perubahan ini ke branch2. Apakah ada cara untuk menerapkan / menggabungkan perubahan ini sehingga menjadi perubahan lokal pada branch2 tanpa melakukan mereka di branch1?

solsberg
sumber
2
Ada Tutorial Git yang hebat di sini di SO. Ini semacam pusat untuk semua pertanyaan git tentang stack overflow.
Decio Lira

Jawaban:

898

Karena file Anda belum berkomitmen di branch1:

git stash
git checkout branch2
git stash pop

atau

git stash
git checkout branch2
git stash list       # to check the various stash made in different branch
git stash apply x    # to select the right one

Seperti yang dikomentari oleh benjohn (lihat git stashhalaman manual ):

Untuk juga menyimpan file yang saat ini tidak terlacak (baru ditambahkan), tambahkan argumen -u, jadi:

git stash -u
VONC
sumber
2
Sama sama. Lebih banyak contoh penggunaan simpanan di unethicalblogger.com/posts/2008/11/… .
VonC
2
Jika Anda mencari solusi untuk masalah yang sama tetapi dengan TFS, solusi yang setara adalah untuk menangguhkan perubahan Anda lalu gunakan TFS Power Tools untuk melepaskan dua belas cabang yang benar menggunakan sakelar / migrasi.
xr280xr
1
Ini berhasil untuk saya. Namun, saya juga harus membuat cabang lokal agar 'stash pop' berfungsi. Periksa stackoverflow.com/questions/1783405/git-checkout-remote-branch jika sesuatu yang serupa terjadi pada Anda.
mimoralea
21
Juga menyimpan saat ini terpantau (baru ditambahkan) file , tambahkan argumen -u, sehingga: git stash -u.
Benjohn
2
@Benjohn Poin bagus. Saya telah memasukkan komentar Anda dalam jawaban untuk lebih banyak visibilitas.
VonC
84

Menyimpan, melakukan sementara dan rebasing mungkin semua berlebihan. Jika Anda belum menambahkan file yang diubah ke indeks, maka Anda mungkin bisa checkout cabang lain.

git checkout branch2

Ini akan berfungsi selama tidak ada file yang Anda edit berbeda antara branch1 dan branch2. Ini akan meninggalkan Anda di branch2 dengan Anda perubahan kerja dipertahankan. Jika mereka berbeda maka Anda dapat menentukan bahwa Anda ingin menggabungkan perubahan lokal Anda dengan perubahan yang diperkenalkan dengan beralih cabang dengan -mopsi untuk checkout.

git checkout -m branch2

Jika Anda telah menambahkan perubahan pada indeks maka Anda ingin membatalkan perubahan ini dengan reset terlebih dahulu. (Ini akan mempertahankan copy pekerjaan Anda, itu hanya akan menghapus perubahan bertahap).

git reset
CB Bailey
sumber
3
Saya pikir simpanan "sederhana" entah bagaimana dipahami, tetapi pendekatan Anda lebih baik dalam memperhitungkan direktori kerja di berbagai cabang. +1
VonC
6
Sebuah checkout tradisional yang sederhana tampaknya lebih sesuai dengan masalah yang ada. checkout beratnya lebih ringan, itu hanya memperbarui file yang perlu diubah. Mungkin lebih mudah untuk memahami pendekatan simpanan, atau mungkin saja itu tidak cukup jelas bahwa checkout 'aman' dalam kasus penggunaan ini.
CB Bailey
Jika checkout -mtidak "aman" dalam beberapa situasi (mungkin itu akan menyebabkan konflik gabungan), apakah simpanan akan memberikan keuntungan (misalnya, bisakah Anda mencopot pop simpanan)?
Craig McQueen
1
@craigMcQueen Anda tidak dapat membatalkan penghapusan simpanan yang muncul tetapi simpanan akan mengeluh tentang konflik saat Anda menghapusnya. Anda dapat memperbaiki konflik dan kemudian melakukan, tetapi simpanan asli masih di tumpukan dalam kasus ini! :)
Shaun F
Jika terjadi konflik gabungan, bukankah file dicadangkan .orig?
jocull
13

Alternatif yang lebih pendek dari pendekatan simpanan yang disebutkan sebelumnya adalah:

Pindahkan sementara perubahan ke simpanan.

  1. git stash

Buat dan alihkan ke cabang baru dan kemudian masukkan simpanan ke cabang itu hanya dalam satu langkah.

  1. git stash branch new_branch_name

Lalu adil adddan commitperubahan ke cabang baru ini.

rbento
sumber
10

PERINGATAN: Tidak untuk pemula git.

Ini muncul cukup dalam alur kerja saya bahwa saya hampir mencoba untuk menulis perintah git baru untuk itu. git stashAliran biasa adalah cara untuk pergi tetapi sedikit canggung. Saya biasanya membuat komitmen baru terlebih dahulu karena jika saya telah melihat perubahan, semua informasi baru dalam pikiran saya dan lebih baik untuk memulai git commitapa yang saya temukan (biasanya perbaikan bug milik master yang saya temukan saat mengerjakan sebuah cabang fitur) segera.

Juga bermanfaat — jika Anda sering menghadapi situasi seperti ini — memiliki direktori kerja lain di samping direktori Anda saat ini yang selalu masterdiperiksa cabang.

Jadi bagaimana saya mencapai ini seperti ini:

  1. git commit perubahan segera dengan pesan komit yang baik.
  2. git reset HEAD~1 untuk membatalkan komit dari cabang saat ini.
  3. (opsional) terus bekerja pada fitur.

Kadang-kadang nanti (tidak sinkron), atau langsung di jendela terminal lain:

  1. cd my-project-master yang merupakan WD lain berbagi sama .git
  2. git reflog untuk menemukan perbaikan bug yang baru saja saya buat.
  3. git cherry-pick SHA1 dari komit.

Opsional (masih asinkron) Anda kemudian dapat rebase (atau menggabungkan) cabang fitur Anda untuk mendapatkan perbaikan bug, biasanya ketika Anda akan mengirimkan PR dan telah membersihkan cabang fitur Anda dan WD sudah:

  1. cd my-project yang merupakan WD utama yang sedang saya kerjakan.
  2. git rebase master untuk mendapatkan perbaikan bug.

Dengan cara ini saya dapat terus bekerja pada fitur tanpa gangguan dan tidak perlu khawatir tentang git stash-ing apa pun atau harus membersihkan WD saya sebelum git checkout(dan kemudian memeriksa fitur cabang backout lagi.) Dan masih memiliki semua perbaikan bug saya pergi masterbukannya disembunyikan di cabang fitur saya.

IMO git stashdan git checkoutmerupakan PIA nyata ketika Anda sedang mengerjakan beberapa fitur besar.

chakrit
sumber
Alternatif yang menarik dan valid untuk jawaban saya. +1
VonC
Apakah Anda berasal dari lincah? The my-project-masterberbagi sama .gitmerek terdengar seperti itu. Mengapa tidak git checkout -b bugfixABC; git commit -a; git reset HEAD^ --hard, kemudian (asynchronous) saat master, git cherry-pick <SHA1 of the commit(s) in bugfixABC? (atau bahkan, untuk menghindari keharusan mengetahui SHA1,, git rebase --onto master feature bugfixABCdari cabang mana pun Anda berada saat ini. Yang berarti Anda bisa melakukan itu langsung setelah yang di git resetatas, selagi feature.)
Gauthier
Namun, OP terdengar seperti mereka tidak siap untuk melakukan perubahan, dalam hal checkout -mini lebih baik.
Gauthier
2

Jika itu tentang perubahan yang dilakukan, Anda harus melihat pada git-rebase, tetapi seperti yang ditunjukkan dalam komentar oleh VonC, ketika Anda berbicara tentang perubahan lokal, git-simpanan tentu akan menjadi cara yang baik untuk melakukan ini.

claf
sumber
Saya tidak mengerti solusi ini: itu akan menulis ulang komit sejarah branch2 dari branch1 ... mengapa mendapatkan semua perubahan yang dilakukan dari branch1 di branch2 ketika kita hanya ingin mendapatkan perubahan lokal yang tidak berkomitmen dari branch1 di branch2? ...
VonC
@VonC: setuju, dalam hal ini, rebase mendapatkan semua perubahan yang dilakukan sejak penggabungan terakhir antar cabang menjadi branch1. Saya tidak mendapatkan parameter "tidak berkomitmen" pada pertanyaan ini pada awalnya. rebase bukan jawaban yang bagus.
claf
@claferri: pfew ... Saya mulai sakit kepala;) Saya akan menurunkan jawaban Anda, tetapi karena saya sendiri menerbitkannya, ada "konflik kepentingan yang jelas". Dengan posting Anda yang diperbarui, saya tidak perlu melakukan downvote sama sekali sekarang. Terima kasih :)
VonC
@VonC: lain kali, jangan ragu untuk memberikan suara selama jawaban saya salah seperti ini;)
claf
1

Jawaban yang diberikan sejauh ini tidak ideal karena mereka membutuhkan banyak pekerjaan yang tidak perlu untuk menyelesaikan konflik penggabungan, atau mereka membuat terlalu banyak asumsi yang sering salah. Ini adalah cara melakukannya dengan sempurna. Tautannya ke situs saya sendiri.

Bagaimana Berkomitmen pada Cabang Lain di git

Anda memiliki perubahan tanpa komitmen pada komitmen my_branchyang ingin Anda komit master, tanpa melakukan semua perubahan dari my_branch.

Contoh

git merge master
git stash -u
git checkout master
git stash apply
git reset
git add example.js
git commit
git checkout .
git clean -f -d
git checkout my_branch
git merge master
git stash pop

Penjelasan

Mulailah dengan menggabungkan masterke cabang Anda, karena bagaimanapun Anda harus melakukan itu pada akhirnya, dan sekarang adalah waktu terbaik untuk menyelesaikan konflik apa pun.

The -upilihan (alias --include-untracked) di git stash -umencegah Anda dari kehilangan file yang tidak terlacak saat nanti lakukan git clean -f -ddalam master.

Setelah git checkout masteritu penting bahwa Anda TIDAK git stash pop, karena Anda akan membutuhkan simpanan ini nanti. Jika Anda pop simpanan dibuat dalam my_branchdan kemudian melakukan git stashdi master, Anda akan menyebabkan konflik merge perlu ketika Anda nantinya menerapkan simpanan yang di my_branch.

git resetunstages semua yang dihasilkan dari git stash apply. Misalnya, file yang telah dimodifikasi di simpanan tetapi tidak ada di masterdipentaskan sebagai konflik "dihapus oleh kami".

git checkout .dan git clean -f -dbuang semua yang tidak dilakukan: semua perubahan pada file yang dilacak, dan semua file dan direktori yang tidak dilacak. Mereka sudah disimpan di simpanan dan jika dibiarkan masterakan menyebabkan konflik penggabungan yang tidak perlu saat beralih kembali ke my_branch.

Yang terakhir git stash popakan didasarkan pada yang asli my_branch, dan karenanya tidak akan menyebabkan konflik penggabungan. Namun, jika simpanan Anda berisi file-file yang tidak terlacak yang telah Anda komit untuk dikuasai, git akan mengeluh bahwa itu "Tidak dapat mengembalikan file-file yang tidak dilacak dari simpanan". Untuk menyelesaikan konflik ini, menghapus file-file dari pohon Anda bekerja, maka git stash pop, git add ., dan git reset.

Vladimir Kornea
sumber
2
Jawaban Anda tidak dihapus karena tertaut ke situs web Anda, itu dihapus karena identik dengan jawaban lain ini dari akun lain. Saya melihat bahwa akun lain memiliki profil yang sama dengan Anda, apakah Anda menggunakan dua akun? Anda dapat menggabungkan kedua akun. Tandai juga mod untuk menjelaskan situasinya, dan Anda bisa mendapatkan jawaban asli Anda (dengan upvote) tidak terhapus.
1
Anda tidak dapat menjaga mereka terpisah jika mereka bergabung, tetapi Anda yang diperbolehkan untuk memiliki beberapa account, selama Anda tidak menggunakannya untuk melakukan voting penipuan (atau memiliki mereka berinteraksi satu sama lain pada umumnya). Jelaskan situasi Anda ke mod. Selain itu, penghapusan adalah kesalahan jujur, bagaimana Anda bisa mengharapkan orang lain mengatakan bahwa Anda menggunakan dua akun yang berbeda?
3
Anda perlu menandai pos Anda dan menggunakan opsi Lain untuk mendapatkan perhatian mod, mereka tidak akan memperhatikan ketika Anda mengedit jawaban Anda yang dihapus. Saya sudah menandai posting Anda untuk perhatian mod, tetapi mereka cukup sibuk, jadi bersabarlah, mereka akhirnya akan menghubungi Anda.
1
Jangan memposting konten duplikat, terutama dari akun yang berbeda. Pilih atau panji untuk menutup sebagai duplikat jika dua pertanyaan sama.
Bill the Lizard