Şube işaretçisini ödeme yapmadan farklı işlemlere taşıma


760

Teslim alınmış bir dalın dal işaretçisini hareket ettirmek için git reset --hardkomut kullanılabilir. Ancak, kontrol edilmemiş bir dalın şube işaretçisini farklı bir taahhüde işaret etmek için nasıl hareket ettiririz (izlenen uzak dal gibi diğer tüm şeyleri tutmak)?


11
Yapmak istediğiniz tek şey, şu an yaratıldığından farklı bir taahhütten bir dal gibi geliyor. Anlayışım doğruysa, neden oluşturmak istediğiniz taahhütten git branch <branch-name> <SHA-1-of-the-commit>eski dalı kullanmaktan ve dökümünden yeni bir dal oluşturmuyorsunuz ?
yasouser

6
@yasouser - "Master" dalının ne olursa olsun iyi bir fikir olduğundan emin değilim.
Bulwersator

Yanıtlar:


578

Bunu keyfi başvurular için yapabilirsiniz. Şube işaretçisini şu şekilde hareket ettirebilirsiniz:

git update-ref -m "reset: Reset <branch> to <new commit>" refs/heads/<branch> <commit>

Genel form:

git update-ref -m "reset: Reset <branch> to <new commit>" <ref> <commit>

İsterseniz reflog mesajıyla ilgili nitleri seçebilirsiniz - branch -fBirinin diğerinden farklı olduğuna inanıyorum reset --hardve bu tam olarak bunlardan biri değil.


39
Mesaj nerede iyi? Nerede saklanır ve daha sonra nasıl okunur?
Mot

4
NOT: Bu çıplak depolarda çalışmaz. Çıplak depolarda, dalı güncellemek için 'git branch -f master <commit>' kullanmanız gerekir (aşağıdaki cevaba bakınız).
Haziran Rodos

37
Benim gibi yanlışlıkla refs / heads / <branch> yerine <branch> kullanırsanız .git / <branch> adresindeki .git dizininizde yeni bir dosya alırsınız ve onunla çalışmaya çalıştığınızda "refname 'master' belirsiz". Düzeltmek için dosyayı .git dizininizden silebilirsiniz.
David Minor

34
Bunun neden daha iyi olduğu memnuniyetine açıklanmamıştır git branch -f. Spesifik olarak, bu yöntemin şu şekilde olduğu görülmektedir: (A) kullanımı daha zor (B) hatırlanması daha zor ve (C) daha tehlikeli
Steven Lu

10
"keyfi refs ile tam olarak ne kastedilmektedir" - Şubeler bir taahhüdüne işaret eden tek tür refordur. Etiketler vardır ve kendiniz ne şube ne de etiket olmayan keyfi ref / / whatevs / myref stili refs oluşturabilirsiniz. Bunun Steven Lu'nun bunun "daha iyi" olabileceği sorusunu da yanıtladığına inanıyorum. Şube katılıyorum - f dalları ile çalışıyorsanız en basit.
Adam A

964
git branch -f <branch-name> <new-tip-commit>

24
Veya keyfi başvurular için git update-ref -m "reset: Reset <branch> to <new commit>" <branch> <commit>. (İsterseniz reflog mesajıyla ilgili niteleri seçebilirsiniz - birinin ondan branch -ffarklı olduğuna inanıyorum reset --hardve bu tam olarak bunlardan hiçbiri değil.)
Cascabel

4
Jefromi, lütfen oy alabilmek için ayrı bir cevap yazın. :)
Mot

16
Bu daha iyi bir yanıttır, çünkü% 99 vakayı ele alır ve aslında belgelere uygundur. git help branch"-f, --force <branchname> zaten varsa <branchname> öğesini <başlangıç ​​noktası> olarak sıfırlayın. -f git dalı olmadan var olan bir dalı değiştirmeyi reddeder."
AlexChaffee

12
Ben yapıyorum git branch -f master <hash>ve bana söylüyor fatal: Cannot force update the current branch.Ummmm ben, şimdi ne yapacağını ben bu komutu kullanma iznim önce bazı diğer rasgele şube kontrol etmek zorunda?
Qwertie

20
Taşınmaya çalıştığınız dal geçerli dalınızsa (bu HEADnoktaya işaret eder) çalışmaz .
Vladimir Panteleev

135

Ayrıca geçebilirsiniz git reset --hard bir taahhüt başvurusu .

Örneğin:

git checkout branch-name
git reset --hard new-tip-commit

Yarı sık böyle bir şey yapıyorum:

Bu tarihi varsayarsak

$ git log --decorate --oneline --graph
* 3daed46 (HEAD, master) New thing I shouldn't have committed to master
* a0d9687 This is the commit that I actually want to be master

# Backup my latest commit to a wip branch
$ git branch wip_doing_stuff

# Ditch that commit on this branch
$ git reset --hard HEAD^

# Now my changes are in a new branch
$ git log --decorate --oneline --graph
* 3daed46 (wip_doing_stuff) New thing I shouldn't have committed to master
* a0d9687 (HEAD, master) This is the commit that I actually want to be master

Bu, dalın ucunu zamanda geri taşımak için tipik olarak HEAD veya HEAD ^ kullanması açısından en mantıklıdır. Dolayısıyla bu, ilerideki taahhüdü belirtmek için tutarlıdır.
justingordon

11
Çalışma ağacınız temizse bu iyi olur. Çok sayıda aşamalı veya işaretsiz değişikliğiniz varsa, git update-refyukarıda tartışıldığı gibi yapmanız daha iyidir .
ücretli bir inek

16
“Cevabınızın” zaten sorunun bir parçası olmayan hiçbir şey eklemediğini fark ettiniz mi? - OP dedi: Eğer kontrol edilirse ... kullanabilirsiniz git reset --hard ...Tekrar burada gerek yok! :-(
Robert Siemer

6
@Robert: Kabul etmiyorum. Soru nasıl kullanılacağını söylemedi ve bu da öyle. Böyle bakmak için gitmek zorunda değil güzeldi.
Wilson F

7
@WilsonF, belki bunu burada bulman güzeldi ama soruya hiç cevap vermiyor. Belki başka bir sorunun cevabıdır, ama burada yanlış .
Robert Siemer

52

Sadece tartışmayı zenginleştirmek için, myBranchşubeyi mevcut taahhüdünüze taşımak istiyorsanız , ikinci argümanı atlayın.-f

Misal:

git branch -f myBranch


Bunu genellikle rebaseMüstakil HEAD durumundayken yaparım :)


13

İçinde gitk --all:

  • İstediğiniz taahhüdü sağ tıklayın
  • -> yeni şube oluştur
  • mevcut bir şubenin adını girin
  • o adın eski dalının değiştirildiğini onaylayan iletişim kutusundaki return tuşuna basın .

Mevcut dalı değiştirmek yerine yeniden oluşturmanın izleme dalı bilgilerini kaybedeceğini unutmayın . (Bu genellikle yalnızca bir uzaktan kumandanın bulunduğu ve yerel şubenizin uzaktan kumandadaki ilgili dal ile aynı ada sahip olduğu basit kullanım durumları için bir sorun değildir. Daha fazla ayrıntı için yorumlara bakın, bu dezavantajı işaret ettiğiniz için @mbdevpl teşekkürler.)

gitkİletişim kutusunun 3 seçeneğe sahip olduğu bir özellik olsaydı havalı olurdu : üzerine yazma, mevcut değişikliği veya iptal etme.


Normalde benim gibi bir komut satırı bağımlısı olsanız git guive gitkizin verdikleri git kullanımının alt kümesi için oldukça güzel tasarlanmış olsalar bile. Onları iyi oldukları için kullanmanızı şiddetle tavsiye ederim (yani, git gui'deki dizinin içine / dışına seçici olarak sahneleme ve ayrıca taahhütte bulunma. (Ctrl-s imzalamak için: line, ctrl-enter işlemek .)

gitk yukarı akış göndermek için değişikliklerinizi güzel bir yama serisine ya da birden çok dalla ortasında ne olduğunuzu takip etmeniz gereken başka bir şeye dönüştürürken birkaç dalı takip etmek için harikadır.

Açık bir grafik dosya tarayıcım bile yok, ama gitk / git gui'yi seviyorum.


1
Çok kolay! Gitg'den gitk'e geçtim.
Michael Cole

Ancak bu şekilde izleme dalı bilgileri kaybolur.
mbdevpl

@mbdevpl: Gerçekten bir git uzmanı değilim. Ne demek istediğinizi anladığımı düşünüyorum, ama sonuçları değil. Bunu oldukça sık kullandım ve hala bu dalları uzaktan kumandadaki aynı isimdeki şubelere itebildim. Bir şube ile uzaktan izleme kolu arasındaki ilişki sizin için ne yapar?
Peter Cordes


1
@PeterCordes Ineed, şube adları eşleşmediğinde önemlidir. Ayrıca birden fazla uzaktan kumanda olduğunda. Ayrıca, şube durumunu görüntülemek için git komut istemini kullandığınızda, izleme şubenize (ayarlanmışsa) kesin mesafeyi gösterir. Ayrıca, git statusçıktı etkilenir. Ayrıca, bazı durumlarda git fetchve git pushizleme şube set yok açıkça uzaktan belirtmeden çalışmayacaktır. Tüm vakaları bilmiyorum, ama benim için genel kural, kolaylık ve çalışma hızı için, takip şubelerinin sırayla olması daha iyi.
mbdevpl

7

Önerilen çözümgit branch -f branch-pointer-to-move new-pointer de TortoiseGit :

  • "Git Günlüğü göster"
  • "Tüm Şubeler" i kontrol edin
  • Şube işaretçisinin (yeni işaretçi) taşınmasını istediğiniz satırda:
    • "Bu sürümde Şube Oluştur" u sağ tıklayın
    • "Dal" ın yanına, taşınacak dalın adını girin (dal-işaretçi-taşınacak)
    • "Base On" altında, yeni işaretçinin doğru olup olmadığını kontrol edin
    • "Zorla" yı kontrol edin
    • Tamam

resim açıklamasını buraya girin

resim açıklamasını buraya girin


4

Dürüst olmak gerekirse, kimsenin git pushkomuta hakkında nasıl düşünmediğine şaşırdım :

git push -f . <destination>:<branch>

Nokta (.) Yerel veri havuzunu ifade eder ve hedef "uzaktaki karşıtının arkasında" olabileceğinden -f seçeneğine ihtiyacınız olabilir .

Bu komut sunucunuzdaki değişikliklerinizi kaydetmek için kullanılsa da, sonuç uzak dalı ( <branch>) yerel dalla ( <destination>) aynı işleme taşımakla aynıdır.


Bunu, -fyerel bir şeyi hızlandırmaktan kaçınmadan da yapabilirsiniz ; örneğin, git fetch origin && git push . origin/develop:developkasaya ihtiyaç duyulmayan başarısız hızlı bir versiyonudurgit checkout develop && git pull --ff-only
btown

1

Dosyayı açın ve .git/refs/heads/<your_branch_name>orada saklanan karmayı, şubenizin başını taşımak istediğiniz kareyle değiştirin. Dosyayı herhangi bir metin düzenleyicisiyle düzenleyin ve kaydedin. Değiştirilecek dalın geçerli olan etkin olmadığından emin olun.

Feragatname: Muhtemelen bunu yapmak için tavsiye edilen bir yol değildir, fakat işi yapar.


1
Bunun kaotik veya kötü bir yol olup olmadığından emin değilim. 🤔 😉
Keith Russell

@KeithRussell her ikisi de olabilir: P
Guillermo Gutiérrez

0

İşaret etmek istediğiniz taahhüdün geçerli dalın önünde olması durumunda (geçerli dalın son taahhütlerini geri almak istemiyorsanız durum böyle olmalıdır), şunları yapabilirsiniz:

git merge <commit>

Soru, şubeye teslim edilmezse ne yapılacağını sordu.
Keith Russell

Hata! Bu noktayı kaçırdım. Bu durumda git push . <commit>:<branch>, daha önce önerildiği gibi yapabilirsiniz .
Jean Paul
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.