Bagaimana cara saya bergerak maju dan mundur antara komit di git?

105

Saya melakukan a git bisectdan setelah sampai pada komit bermasalah, saya sekarang mencoba untuk melangkah maju / mundur untuk memastikan saya berada di langkah yang benar.

Saya tahu HEAD^harus mundur dalam sejarah tetapi apakah ada jalan pintas lain untuk membawa saya maju (menuju komitmen tertentu di masa depan) seperti:

A - B - C(HEAD) - D - E - F

Saya tahu bahwa target saya adalah F dan saya ingin pindah dari C ke D .


CATATAN: ini bukan duplikat Git: Bagaimana cara berpindah-pindah antar commit , pertanyaan saya sedikit berbeda dan tidak terjawab di sana

Kostas
sumber
git checkout -b new_branch HEAD~4untuk kembali 4 komit dari HEAD seperti di stackoverflow.com/a/4940090/911945
Anton Tarasenko

Jawaban:

57

Saya telah bereksperimen sedikit dan ini tampaknya melakukan trik untuk menavigasi ke depan ( edit : ini berfungsi dengan baik hanya ketika Anda memiliki riwayat linier tanpa melakukan penggabungan):

git checkout $(git rev-list --topo-order HEAD..towards | tail -1)

di mana towardsSHA1 dari komit atau tag.

Penjelasan:

  • perintah di dalam $()berarti: dapatkan semua komit antara saat ini HEADdan towardskomit (tidak termasuk HEAD), dan urutkan mereka dalam urutan prioritas (seperti git logsecara default - alih-alih urutan kronologis yang anehnya default untuk rev-list), dan kemudian ambil yang terakhir ( tail), yaitu yang ingin kita tuju.
  • ini dievaluasi di subkulit, dan diteruskan ke git checkoutuntuk melakukan pembayaran.

Anda dapat menentukan fungsi yang dapat diakses sebagai alias yang mengharapkan parameter dalam .profilefile Anda untuk mengarahkan maju menuju komit tertentu:

# Go forward in Git commit hierarchy, towards particular commit 
# Usage:
#  gofwd v1.2.7
# Does nothing when the parameter is not specified.
gofwd() {
  git checkout $(git rev-list --topo-order HEAD.."$*" | tail -1)
}

# Go back in Git commit hierarchy
# Usage: 
#  goback
alias goback='git checkout HEAD~'
jakub.g
sumber
2
Maju bekerja dengan baik di bagian sejarah yang lurus tetapi masuk ke loop saat menghadapi penggabungan.
Kostas
Ya, saya sebenarnya belum mengujinya di penggabungan. Saya akan mencoba untuk melihat-lihat di waktu luang, tetapi saya memiliki sedikit insentif untuk sementara, karena kami telah setuju untuk memiliki sejarah yang sangat linier dalam proyek kami;)
jakub.g
2
Jawaban yang bagus! Dimodifikasi untuk menentukan cabang saat ini secara otomatis: stackoverflow.com/a/23172256/480608
Raine Revere
Ini salah git logmenunjukkan komit dalam urutan kronologis, secara default, sama seperti rev-list, kecuali saat menggunakan --graphbendera.
papiro
Bukti yang cukup meyakinkan bahwa git terlalu rumit. Untuk sesuatu yang biasanya sesederhana Urungkan atau Ulangi, berikut kami memiliki daftar jawaban yang saling bertentangan. Dan saya bahkan belum membahas satu pun jawaban yang terkait. FWIW, saya mencoba versi ini dengan serangkaian komitmen linier sederhana dan akhirnya menyerah begitu saja.
Snowcrash
49

Yang Anda butuhkan untuk memperjelas, bukan status kepala terpisah adalah menyetel ulang, bukan melakukan pembayaran.

git reset HEAD@{1}
d3day
sumber
5
atau git reset "HEAD@{1}"pada cangkang tertentu seperti fish dan PowerShell .. git reflogjuga dapat berguna untuk menemukan komit yang benar.
steve cook
1
Selalu gunakan tanda kutip tunggal dalam perintah shell kecuali Anda secara eksplisit ingin shell mencoba menafsirkan / memperluas konten. Ini sangat penting dalam kasus seperti ini, di mana tujuannya adalah untuk mencegah shell menafsirkan karakter khusus. Dengan begitu, Anda tidak perlu mengetahui apakah string berisi sesuatu yang bermasalah.
Chris Halaman
Saya melakukan itu untuk melihat ke masa lalu, lalu saya melakukannya git reset HEADuntuk kembali ke tempat saya dulu ... sekarang saya tidak tahu di mana keadaan tempat penyimpanan saya dan semuanya menakutkan. Apa yang harus saya lakukan sekarang?
theonlygusti
47

Saya yakin Anda bisa melakukan:

git reset HEAD@{1}

Untuk maju satu komitmen pada waktunya. Untuk maju beberapa komit, gunakan HEAD @ {2}, HEAD @ {3}, dll.

w0utert.dll
sumber
20

Inilah yang saya gunakan untuk menavigasi bolak-balik.

pindah ke komit berikutnya

function n() {
    git log --reverse --pretty=%H master | grep -A 1 $(git rev-parse HEAD) | tail -n1 | xargs git checkout
}

pindah ke komit sebelumnya

function p() {
    git checkout HEAD^1
}
MK
sumber
Terima kasih! Saya menggunakan ini sekarang! Catatan untuk pemula lain seperti saya : untuk memasang kembali HEAD, git checkout <current branch>lampirkan ke commit terbaru. git checkout -b <new-branch-name>dari komit saat ini memungkinkan perubahan di cabang baru. git rebase -ijuga bekerja. Juga , saya menamai n()fungsi saya nx()untuk menghindari konflik dengan manajer versi node "n". Pastikan untuk memeriksa alias!
Steven Choi
function () {...} adalah untuk membuat file skrip bash Unix / Linux, saya berasal dari Windows, agak sulit bagi saya untuk memahaminya terlebih dahulu
IcyBrk
9

Katakanlah F adalah komit terbaru pada trunk(masukkan nama cabang Anda sendiri di sini) ... Anda dapat merujuknya sebagai trunk~0(atau hanya trunk), E sebagai trunk~1, D sebagaitrunk~2 dll.

Lihat reflog Anda untuk mengetahui lebih banyak cara untuk memberi nama komitmen.

Tak berguna
sumber
1
~ kembali, bukan foward, trunk ~ 2 adalah A
EmmanuelMess
Iya. Jawaban ini mengasumsikan Anda memiliki cabang yang disebut trunking toF , dan Anda tahu di mana dalam sejarah cabang itu Anda ingin pindah. Ini tidak mencoba untuk bergerak maju relatif terhadap HEAD, tetapi kurang jauh ke belakang dibandingkan dengan trunk.
berguna
@EmmanuelMess bagaimana trunk~2A?
theonlygusti
@theonlygusti Anda mundur dari HEAD dua kali.
EmmanuelMess
Anda masih berasumsi bahwa cabang trunkdan arus Anda HEADidentik tidak diperlihatkan dalam pertanyaan, yang saya nyatakan bukan seperti yang saya asumsikan, dan yang sangat tidak mungkin di tengah jalanbisect
berguna
3

Melintasi mundur itu sepele karena Anda sedang turun dari pohon, dan selalu ada satu cara untuk pergi

  function git_down
        git checkout HEAD^
  end

Saat melakukan traverse maju Anda bergerak ke atas pohon, jadi Anda perlu menjelaskan cabang mana yang Anda targetkan:

  function git_up 
        git log --reverse --pretty=%H $argv | grep -A 1 (git rev-parse HEAD) | tail -n1 | xargs git checkout
  end

Penggunaan: git down,git up <branch-name>

Dziamid
sumber
Mundur juga tidak sepenuhnya unik, saat penggabungan terlibat. Padahal HEAD^biasanya default yang wajar.
kdb
2

Jika Anda ingin melihat ke depan, Anda dapat melakukan trik ini, karena Git tidak memiliki perintah yang ketat untuk itu.

git log --reverse COMMIT_HASH..

Contoh

Daftar hash riwayat log:

A
B
C -> put this
D

menggunakan perintah git log --reverse C.., output Anda akan melihat B dan A .

dimpiax
sumber
1

Mungkin bukan cara terbaik tetapi Anda dapat menggunakan git loguntuk melihat daftar komit dan kemudian gunakan git checkout [sha1 of D]untuk pindah ke D.

bb-generasi
sumber
6
Saya tidak mengerti, jika dia di C, maka git log hanya akan menampilkan C, B dan A.
Bilthon
Oke, mengerti, tetapi Anda harus melakukan git-log yang rumit seperti yang ditunjukkan pada tautan yang diberikan oleh VonC
Bilthon
1

Saya baru saja melakukan tes untuk ini. katakan misalnya Anda berada di cabang master Kemudian lakukan:

git checkout HEAD@{3}

Jadi head terlepas, dan Anda dapat mencobanya lagi untuk beralih ke commit lain:

git checkout HEAD@{4}

Setelah Anda selesai melihat-lihat, Anda dapat kembali ke keadaan semula hanya dengan memeriksa ke cabang itu. Dalam contoh saya: cabang master

git checkout master

Jika Anda tidak ingin pergi ke keadaan semula, dan ingin tetap salah satu komit sebagai kepala Anda dan melanjutkan dari sana, maka Anda perlu keluar dari sana. misalnya setelah "git checkout HEAD @ {4}", Anda dapat mengeluarkan

git checkout -b MyNewBranch
pengguna1322977
sumber
0

Sebagai solusinya, Anda bisa kembali ke HEAD dengan

git checkout <branch>

Dan kemudian pindah ke komit yang Anda inginkan, dengan

git checkout HEAD~<offset>
Patrizio Bertoni
sumber
0

Jika Anda menggunakan kode vs maka riwayat Git adalah plugin yang luar biasa di mana Anda dapat secara efisien melihat komit dan memeriksa kontennya di editor itu sendiri. lihat tautannya

Rahil Ahmad
sumber
0
branchName=master; commitInOrder=1; git checkout $(git log --pretty=%H "${branchName}" | tac | head -n "${commitInOrder}" | tail -n 1)

dimana:

branchName sama dengan nama cabang

commitInOrder sama dengan komit dalam urutan dari komit pertama di cabang yang dipilih (jadi 1 adalah komit pertama, 2 komit kedua di cabang, dll.)

tamu
sumber