Git'te işlemeler arasında nasıl ileri ve geri hareket ederim?


105

Bir yapıyorum git bisectve sorunlu taahhüdüne ulaştıktan sonra, şimdi doğru adımda olduğumdan emin olmak için ileri / geri bir adım atmaya çalışıyorum.

HEAD^Tarihte geriye gitmeyi biliyorum, ancak beni ilerletmek için (gelecekte belirli bir taahhüde doğru) başka bir kısayol var mı:

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

Benim hedef olduğunu biliyoruz F ve nereden taşımak istediğiniz C'ye kadar D .


NOT: Bu Git'in bir kopyası değil : İşlemler arasında nasıl gidip gelirim , sorum biraz farklı ve orada cevaplanmıyor



git checkout -b new_branch HEAD~4stackoverflow.com/a/4940090/911945'te
HEAD'den

Yanıtlar:


57

Biraz deney yaptım ve bu ileriye gitmek için hile yapıyor gibi görünüyor ( düzenleme : yalnızca birleştirme işlemlerinin olmadığı doğrusal bir geçmişiniz olduğunda iyi çalışır):

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

kayıt towardsveya etiketin SHA1'i nerede .

Açıklama:

  • içerideki komut şu $()anlama gelir: geçerli HEADve towardscommit (hariç HEAD) arasındaki tüm commit'leri alın ve bunları öncelik sırasına göre sıralayın ( git logtuhaf bir şekilde varsayılan olan kronolojik sıra yerine - varsayılan olarak rev-list) ve sonra sonuncuyu alın ( tail), yani gitmek istediğimiz kişi.
  • bu alt kabukta değerlendirilir ve bir ödünç alma git checkoutgerçekleştirmek için geçilir .

.profileBelirli bir kaydetmeye doğru ilerlemek için dosyanızda parametre bekleyen bir takma ad olarak erişilebilen bir işlevi tanımlayabilirsiniz :

# 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~'

2
İleriye gitmek, tarihin düz kısımlarında iyi çalışır, ancak bir birleştirme ile karşılaşıldığında döngülere girer.
Kostas

Evet, aslında birleşmelerde test etmedim. Boş zamanlara bakmaya çalışacağım, ancak projemizde kesinlikle doğrusal bir geçmişe sahip olmayı kabul ettiğimiz için geçici olarak çok az
teşvikim var

2
Mükemmel cevap! Geçerli dalı otomatik olarak belirtmek için değiştirildi: stackoverflow.com/a/23172256/480608
Raine Revere

Bu yanlış. git log, varsayılan olarak rev-list, --graphbayrak kullanımı haricinde olduğu gibi , kaydetmeleri kronolojik sırada gösterir .
papiro

Git'in çok karmaşık olduğuna dair oldukça ikna edici kanıt. Genellikle Geri Al veya Yinele kadar basit olan bir şey için, burada çılgın bir çelişkili cevaplar listemiz var. Ve bağlantılı cevapların hiçbirine girmedim bile. FWIW, bunun bir versiyonunu basit bir doğrusal işlem kümesiyle denedim ve sonunda pes ettim.
Snowcrash

49

Tek yapmanız gereken, bağımsız kafa durumu değil, sıfırlamaktır, kontrol etmek değil.

git reset HEAD@{1}

5
veya git reset "HEAD@{1}"balık ve powershell gibi belirli kabuklarda .. git reflogdoğru commit'i bulmak için de yararlı olabilir.
steve cook

1
Kabuğun içeriği yorumlamayı / genişletmeyi açıkça istemediğiniz sürece, kabuk komutlarında her zaman tek tırnak kullanın. Bu, amacın kabuğun özel karakterleri yorumlamasını engellemek olduğu bu gibi durumlarda özellikle önemlidir. Bu şekilde, dizenin sorunlu bir şey içerip içermediğini bilmenize gerek kalmaz.
Chris Page

Bunu zamanda geriye bakmak için yaptım, sonra olduğum git reset HEADyere geri döndüm ... şimdi depomun hangi durumda olduğu hakkında hiçbir fikrim yok ve her şey korkutucu. Ben şimdi ne yapmalıyım?
theonlygusti

47

Yapabileceğine inanıyorum:

git reset HEAD@{1}

Zaman içinde bir taahhüdü ileri götürmek. Birden çok kaydetmeyi ileri almak için HEAD @ {2}, HEAD @ {3} vb. Kullanın.


20

İleri geri gezinmek için kullandığım şey bu.

sonraki işleme geçmek

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

önceki işleme geçiş

function p() {
    git checkout HEAD^1
}

Teşekkürler! Bunu şimdi kullanıyorum! Benim gibi diğer yeni başlayanlar için notlar : HEAD'i yeniden git checkout <current branch>eklemek için, en son işlemeye eklenir. git checkout -b <new-branch-name>geçerli kaydetmeden yeni dalda değişikliklere izin verir. git rebase -iayrıca çalışır. Ayrıca , n()işlevimi nx()düğüm sürüm yöneticisi ile çakışmaması için "n" olarak adlandırdım. Takma adları kontrol ettiğinizden emin olun!
Steven Choi

function () {...} bir Unix / Linux bash betik dosyası yazmak içindir, Windows'tan geliyorum, ilk olarak benim için biraz zor anlıyorum
IcyBrk

9

F'nin en son işlem olduğunu söyleyin trunk(buraya kendi dal adınızı girin) ... ona trunk~0(veya sadece trunk), E as trunk~1, D trunk~2vb. Olarak başvurabilirsiniz .

Kayıtları adlandırmanın başka yolları için reflog'unuza bir göz atın .


1
~ geri döner, foward değil, gövde ~ 2
EmmanuelMess

Evet. Bu yanıt F, gövde adlı bir dalınız olduğunu ve o dalın geçmişinde nereye gitmek istediğinizi bildiğinizi varsayar . HEAD'e göre ilerlemeye çalışmıyor, ancak gövdeye göre daha az geriye gidiyor.
Yararsız

@EmmanuelMess trunk~2A nasıl ?
theonlygusti

@theonlygusti HEAD'den iki kez geri dönüyorsunuz.
EmmanuelMess

Hala şube olduğunu varsayıyoruz trunkve geçerli HEADolan özdeş değildir olduğunu ben ifade ettik Söz, gösterilen değil ben varsayarak ettiğimi ve hangi bir içinden çok olası yarım yoludurbisect
Yararsız

3

Ağaçta aşağı doğru hareket ettiğiniz için geriye doğru gitmek önemsizdir ve her zaman gidecek bir yol vardır

  function git_down
        git checkout HEAD^
  end

İleriye doğru ilerlerken ağaçta yukarı doğru ilerliyorsunuz, bu nedenle hangi dalı hedeflediğinizi açıkça belirtmeniz gerekir:

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

Kullanımı: git down,git up <branch-name>


Geriye doğru gitmek, birleşmeler söz konusu olduğunda da tamamen benzersiz değildir. Yine HEAD^de genellikle makul bir varsayımdır.
kdb

2

İleriyi görmek istiyorsanız, Git'in kesin bir komutu olmadığı için bu numarayı yapabilirsiniz.

git log --reverse COMMIT_HASH..

Misal

Günlük geçmişi karmalarının listesi:

A
B
C -> put this
D

komut kullanarak git log --reverse C..çıktıda B ve A'yı göreceksiniz .


1

Muhtemelen en iyi yol değil, ancak git logtaahhütlerin listesini görüntülemek için ve ardından git checkout [sha1 of D]D'ye geçmek için kullanabilirsiniz .



Tamam, anladım, ancak VonC
Bilthon

1

Bunun üzerinde bir test yaptım. örneğin ana dalda olduğunuzu söyleyin Sonra yapın:

git checkout HEAD@{3}

Böylece head kopar ve daha sonra başka bir işleme gitmek için tekrar deneyebilirsiniz:

git checkout HEAD@{4}

Etrafınıza bakmayı bitirdikten sonra, sadece o şubeye giderek orijinal halinize geri dönebilirsiniz. Örneğimde: ana dal

git checkout master

Orijinal duruma gitmek istemiyorsanız ve bunu yapmak istiyorsanız, taahhütlerden birini başınız olarak tutun ve oradan devam edin, o zaman oradan ayrılmanız gerekir. örneğin "git checkout HEAD @ {4}" sonrasında,

git checkout -b MyNewBranch

0

Geçici bir çözüm olarak, HEAD'e dönebilirsiniz.

git checkout <branch>

Ve sonra yapmak istediğiniz taahhüde geçin.

git checkout HEAD~<offset>

0

Vs kodu kullanıyorsanız Git geçmişi, commit'leri verimli bir şekilde görebileceğiniz ve içeriklerini düzenleyicinin kendisinde kontrol edebileceğiniz harika bir eklentidir. kontrol linki


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

nerede:

branchName şube adına eşittir

commitInOrder seçilen daldaki ilk kesinleştirme sırasına eşittir (dolayısıyla 1 ilk kesin, 2 daldaki ikinci kesin vb.)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.