pindah berkomitmen (tetapi tidak mendorong) perubahan ke cabang baru setelah menarik

460

Saya telah melakukan sedikit pekerjaan yang adil ("Cabang Anda unggul dari 'asal / master' dengan 37 komitmen.") Yang benar-benar harus pergi ke cabang sendiri daripada ke master. Komit ini hanya ada pada mesin lokal saya dan belum didorong origin, tetapi situasinya agak rumit di mana pengembang lain telah mendorong origin/masterdan saya telah menarik perubahan itu.

Bagaimana cara memindahkan 37 komit lokal saya secara retroaktif ke cabang baru? Berdasarkan dokumen, tampak bahwa git rebase --onto my-new-branch masteratau ...origin/masterharus melakukan ini, tetapi keduanya hanya memberi saya kesalahan "fatal: Needed a single revisi". man git-rebasemengatakan apa-apa tentang memberikan revisi rebasedan contoh-contohnya tidak melakukannya, jadi saya tidak tahu bagaimana menyelesaikan kesalahan ini.

(Perhatikan bahwa ini bukan duplikat dari Pindahkan pekerjaan yang sudah ada dan tidak dikomit ke cabang baru di Git atau Bagaimana cara menggabungkan perubahan tidak mengikat lokal saya ke cabang Git lain? Karena pertanyaan-pertanyaan itu berurusan dengan perubahan yang tidak dikomit di pohon kerja lokal, bukan perubahan yang memiliki telah dilakukan secara lokal.)

Dave Sherohman
sumber
Lihat solusi ini . Tampaknya mudah dan bersih.
Tony
Lihat solusi ini . Tampaknya mudah dan bersih.
Tony

Jawaban:

518

Ini seharusnya baik-baik saja, karena Anda belum mendorong komitmen Anda di tempat lain, dan Anda bebas untuk menulis ulang sejarah cabang Anda setelahnya origin/master. Pertama saya akan menjalankan git fetch originuntuk memastikan bahwa origin/masteritu up to date. Dengan asumsi bahwa Anda sedang aktif master, Anda seharusnya dapat melakukan:

git rebase origin/master

... yang akan memutar ulang semua komit Anda yang tidak origin/masterke origin/master. Tindakan default rebase adalah mengabaikan komit gabungan (mis. Komit yang git pullmungkin Anda perkenalkan) dan itu hanya akan mencoba menerapkan tambalan yang diperkenalkan oleh setiap komit Anda origin/master. (Anda mungkin harus menyelesaikan beberapa konflik di sepanjang jalan.) Kemudian Anda dapat membuat cabang baru berdasarkan hasilnya:

git branch new-work

... lalu atur masterkembali Anda ke origin/master:

# Use with care - make sure "git status" is clean and you're still on master:
git reset --hard origin/master

Ketika melakukan manipulasi cabang semacam ini dengan git branch,, git resetdll. Saya merasa berguna untuk sering melihat grafik commit dengan gitk --allatau alat yang serupa, hanya untuk memeriksa apakah saya memahami di mana semua referensi yang berbeda menunjuk.

Atau, Anda bisa saja membuat cabang topik berdasarkan di mana master Anda berada di tempat pertama ( git branch new-work-including-merges) dan kemudian mengatur ulang masterseperti di atas. Namun, karena cabang topik Anda akan menyertakan gabungan dari origin/masterdan Anda belum mendorong perubahan Anda, saya sarankan melakukan rebase sehingga sejarahnya lebih rapi. (Juga, saat Anda akhirnya menggabungkan cabang topik Anda kembali untuk dikuasai, perubahannya akan lebih jelas.)

Mark Longair
sumber
8
@ Olie: Tidak, jawabannya benar berdasarkan asumsi dalam pertanyaan dan yang saya sebutkan di atas jawaban. Komit yang seharusnya berada di cabang baru yang terpisah sudah masuk master; rebase menulis ulang mastercabang sehingga komit baru secara linear di atas origin/master, kemudian git branch new-workmembuat new-workcabang menunjuk pada ujung master(cabang saat ini) tanpa mengalihkan cabang saat ini ke new-work. Jadi sekarang new-workberisi semua komitmen baru. Kemudian reset akan memindahkan cabang saat ini (masih master) kembali ke origin/master.
Mark Longair
1
@Quintesse: Saya sangat menyesal jika Anda kehilangan pekerjaan, tapi saya yakin jawaban ini benar untuk situasi yang dijelaskan oleh penanya asli. (Saya baru saja menjawab pernyataan Olie semoga klarifikasi.) Bagaimanapun, kalau-kalau itu membantu untuk mendapatkan pekerjaan Anda kembali, saya harus mengatakan bahwa jika pekerjaan Anda dilakukan dalam beberapa hari terakhir (salah satu asumsi dalam pertanyaan dan jawaban ini ) Anda harus dapat dengan mudah mengambilnya melalui git reflog.
Mark Longair
5
@ Olie: mungkin cara yang lebih baik untuk menjelaskan: cabang di git seperti label yang menunjukkan komit tertentu; mereka secara otomatis dipindahkan ke komitmen baru jika Anda membuatnya di cabang itu atau dapat dipindahkan dengan git resetdan berbagai cara lainnya. Itu git branch new-workhanya mengatakan "buat cabang menunjuk komit ini sementara saya tetap di cabang saya saat ini (yang adalah master dalam hal ini)". Jadi tidak perlu memiliki perintah yang memindahkan komit dari master ke cabang baru - Anda cukup membuat cabang baru di sana dan ketika Anda mengatur ulang master, cabang baru ditinggalkan di tempat master berada
Mark Longair
1
agak terlambat ke pesta tapi @Olie, hanya karena status git ketika di cabang baru tidak menunjukkan komit di depan master tidak berarti mereka tidak benar-benar ada (dengan asumsi itu sebabnya Anda khawatir). Coba dorong cabang baru ke asal: Anda akan melihat komit ada di sana
Félix Gagnon-Grenier
2
@ FélixGagnon-Grenier, jangan khawatir tentang "terlambat" - selalu ada orang mencari pertanyaan lama dan setiap klarifikasi membantu. Terima kasih! :)
Olie
148

Jika Anda memiliki # komitmen rendah dan Anda tidak peduli jika ini digabungkan menjadi satu mega-komit, ini bekerja dengan baik dan tidak seseram yang dilakukan git rebase:

unstage file (ganti 1 dengan # dari commit)

git reset --soft HEAD~1

buat cabang baru

git checkout -b NewBranchName

tambahkan perubahan

git add -A

membuat komitmen

git commit -m "Whatever"
Stachu
sumber
5
Untuk menampilkan grafik yang mudah dipahami, silakan gunakan git log --all --decorate --oneline --graph.
EliuX
Hai @EliuX - Saya kehilangan relevansinya di sini. Bisakah kamu berkembang?
Stachu
Ini adalah sesuatu yang berguna untuk memeriksa apakah Anda mendapatkan hasil yang diinginkan dari apa yang Anda lakukan
EliuX
4
Terima kasih!! ini adalah solusi yang sangat sederhana dan bekerja dengan sempurna !!
Chris Sim
91

Saya terjebak dengan masalah yang sama. Saya telah menemukan solusi termudah yang ingin saya bagikan.

1) Buat cabang baru dengan perubahan Anda.

git checkout -b mybranch

2) (Opsional) Tekan kode cabang baru pada server jarak jauh.

git push origin mybranch

3) Checkout kembali ke cabang utama.

git checkout master

4) Atur ulang kode cabang utama dengan server jarak jauh dan hapus komit lokal.

git reset --hard origin/master
NiRmaL
sumber
10
Itu benar-benar cara termudah
dhilt
4
Anda dapat meninggalkan langkah 2. Saya berasumsi bahwa sejak jawaban teratas, git telah berubah dan prosedur ini tidak diizinkan sebelumnya.
Sebastian
Ini jawaban terbaik menurut saya.
Macindows
1
Jawaban ini perlu pindah ke atas. Terima kasih.
amit
27

Satu lagi cara menganggap branch1 - adalah cabang dengan perubahan berkomitmen branch2 - adalah cabang yang diinginkan

git fetch && git checkout branch1
git log

pilih id komitmen yang harus Anda pindahkan

git fetch && git checkout branch2
git cherry-pick commit_id_first..commit_id_last
git push

Sekarang kembalikan komitmen yang tidak dicopot dari cabang awal

git fetch && git checkout branch1
git reset --soft HEAD~1
Andriy
sumber
5
Cherry-pick adalah perintah "salin / pindahkan satu komit" yang terbaik, esp. ketika sejarah adalah bagasi untuk keperluan Anda.
John Neuhaus
Sejauh ini, ini adalah jawaban paling nyaman untuk pertanyaan itu. Terima kasih untuk perintahnya!
Farah
dapatkah Anda memperbarui komentar terakhir di mana 1 atau n adalah jumlah komit yang tidak dicuri? Ini masih merupakan solusi yang sangat bagus untuk pertanyaan ini.
chAlexey
9

Atau, tepat setelah Anda komit ke cabang yang salah, lakukan langkah-langkah ini:

  1. git log
  2. git diff {previous to last commit} {latest commit} > your_changes.patch
  3. git reset --hard origin/{your current branch}
  4. git checkout -b {new branch}
  5. git apply your_changes.patch

Saya bisa membayangkan bahwa ada pendekatan yang lebih sederhana untuk langkah satu dan dua.

Andreas B
sumber
6

Bagaimana dengan:

  1. Cabang dari KEPALA saat ini.
  2. Pastikan Anda menguasai , bukan cabang baru Anda.
  3. git reset kembali ke komit terakhir sebelum Anda mulai membuat perubahan.
  4. git pull untuk menarik kembali hanya perubahan jarak jauh yang Anda buang dengan reset.

Atau akankah itu meledak ketika Anda mencoba untuk menggabungkan kembali cabang?

Tim Keating
sumber
2
Ah, ini pada dasarnya adalah opsi B yang dijelaskan oleh @ Mark-Longair di atas
Tim Keating
2

Ini cara yang lebih sederhana:

  1. Buat cabang baru

  2. Di cabang baru Anda lakukan a git merge master- ini akan menggabungkan perubahan yang Anda komit (tidak didorong) ke cabang baru Anda

  3. Hapus cabang master lokal Anda git branch -D masterGunakan -Dbukan -dkarena Anda ingin memaksa menghapus cabang.

  4. Lakukan saja git fetchpada cabang master Anda dan lakukan git pullpada cabang master Anda untuk memastikan Anda memiliki kode terbaru tim Anda.

A Kok
sumber
1

Pendekatan yang lebih sederhana, yang telah saya gunakan (dengan asumsi Anda ingin memindahkan 4 commit):

git format-patch HEAD~4

(Lihat di direktori tempat Anda mengeksekusi perintah terakhir untuk 4 .patchfile)

git reset HEAD~4 --hard

git checkout -b tmp/my-new-branch

Kemudian:

git apply /path/to/patch.patch

Dalam urutan apa pun yang Anda inginkan.

pengguna1429980
sumber
0
  1. Lihat salinan sumber Anda yang baru

    git clone ........

  2. Buat cabang dari posisi yang diinginkan

    git checkout {position} git checkout -b {branch-name}

  3. Tambahkan repositori jarak jauh

    git remote add shared ../{original sources location}.git

  4. Dapatkan sumber jarak jauh

    git fetch shared

  5. Periksa cabang yang diinginkan

    git checkout {branch-name}

  6. Gabungkan sumber

    git merge shared/{original branch from shared repository}

Sergey Kabashnyuk
sumber
0

Bagi saya ini adalah cara terbaik:

  1. Periksa perubahan dan gabungkan konflik git fetch
  2. Buat cabang baru git branch my-changesdan dorong ke jarak jauh
  3. Ubah hulu ke cabang yang baru dibuat git master -u upstream-branch remotes/origin/my-changes
  4. Dorong komit Anda ke cabang hulu yang baru.
  5. Beralih kembali ke hulu sebelumnya git branch master --set-upstream-to remotes/origin/master
Sebastian
sumber