Git reset --hard ve uzak depoya aktar


201

Üzerinde bazı kötü taahhütleri olan bir havuzum vardı (bu örnek için D, E ve F).

ABCDEF ustası ve kökeni / ustası

Yerel depoyu özellikle bir ile değiştirdim git reset --hard. Sıfırlamadan önce bir şube aldım, bu yüzden şimdi şöyle bir repo var:

A-B-C master  
     \ D-E-F old_master

A-B-C-D-E-F origin/master

Şimdi bu kötü taahhütlerin bazı kısımlarına ihtiyacım vardı, bu yüzden ihtiyacım olan bitleri aldım ve bazı yeni taahhütler yaptım, böylece şimdi yerel olarak aşağıdakilere sahibim:

A-B-C-G-H master
     \ D-E-F old_master

Şimdi bu durumu uzaktan repoya itmek istiyorum. Ancak, bir git pushGit kibarca yapmaya çalıştığımda bana fırça verir:

$ git push origin +master:master --force  
Total 0 (delta 0), reused 0 (delta 0)  
error: denying non-fast forward refs/heads/master (you should pull first)  
To git@git.example.com:myrepo.git  
! [remote rejected] master -> master (non-fast forward)  
error: failed to push some refs to 'git@git.example.com:myrepo.git'  

Uzak repoyu yerel repo'nun geçerli durumunu nasıl alabilirim?


2
Bu birkaç "neredeyse değiştirilmiş geçmiş soruları itmek nasıl" bir kopyası, örneğin cevabını buraya bakın stackoverflow.com/questions/253055/…
CB Bailey

2
Bu doğru ve ben göndermeden önce bir cevap için StackOverflow aramıştı. Ancak aramam sadece git push --force'un sorunu düzelttiği cevapları ortaya çıkardı. Yayınınıza bağladığınız için teşekkürler :)
robertpostill

2
Yakında (git1.8.5, 4. Çeyrek 2013) daha dikkatli bir git push -forceşekilde yapabileceksiniz .
VonC

Yanıtlar:


287

Bir zorlamayı zorlamak işe yaramazsa (" git push --force origin" veya " git push --force origin master" yeterli olursa), uzak sunucunun, take.denyNonFastForwards yapılandırma değişkeni yoluyla hızlı ileri sarma olmayan itmeleri reddettiği anlamına gelebilir ( açıklama için git config kılavuzuna bakın) veya güncelleme / ön alma kancası ile.

Daha eski Git ile " git push origin :master" (şube adından önce ':' 'bölümüne bakın ve sonra " git push origin master" belirtilen dalı yeniden oluşturarak bu kısıtlamaya bir çözüm bulabilirsiniz .

Bunu değiştiremezseniz, DEF'de bir değişiklik geri dönüşü oluşturmak için geçmişi yeniden yazmak yerine tek çözüm olurdu :

ABCDEF - [(DEF) ^ - 1] ana

ABCDEF başlangıç ​​/ master

2
@ JakubNarębski, teşekkürler. get revert HEAD~Nyardım etti. Ntaahhüt sayısıdır. Örneğin, önceki taahhüdüm gerekirse, kullanacağımgit revert HEAD~1
Maksim Dmitriev

1
Ve bunu yaparak yerel herkesi kıracağınızı unutmayın.
Tom Brito

24

Jakub'ın cevabını tamamlamak için, ssh içindeki uzak git sunucusuna erişiminiz varsa, git uzak dizinine gidip şunları ayarlayabilirsiniz:

user@remote$ git config receive.denyNonFastforwards false

Ardından yerel deponuza geri dönün, taahhütlerinizi tekrar yapmayı deneyin --force:

user@local$ git push origin +master:master --force

Ve son olarak sunucunun ayarını orijinal korumalı durumuna geri döndürün:

user@remote$ git config receive.denyNonFastforwards true

Bununla ilgili sourceforge için uyarlanmış bilgiler için ayrıca pete.akeo.ie/2011/02/denying-non-fast-forward-and.html adresine bakın .
hlovdal

DenyNonFastForwards kullanarak devre dışı bırakma hakkında ayrıntılı talimatlar vibu SO yayınında verilmiştir: stackoverflow.com/a/43721579/2073804
ron190


1

Tüm git resetleme işi benim için çok karmaşık görünüyordu.

Ben de birkaç taahhüt önce devlet src klasörü almak için çizgiler boyunca bir şey yaptım

# reset the local state
git reset <somecommit> --hard 
# copy the relevant part e.g. src (exclude is only needed if you specify .)
tar cvfz /tmp/current.tgz --exclude .git  src
# get the current state of git
git pull
# remove what you don't like anymore
rm -rf src
# restore from the tar file
tar xvfz /tmp/current.tgz
# commit everything back to git
git commit -a
# now you can properly push
git push

Bu şekilde, src'deki işlerin durumu bir tar dosyasında tutulur ve git, çok fazla uğraşmadan bu durumu kabul etmek zorunda kalır, temel olarak src dizini, birkaç işlemden önce bulunduğu durumla değiştirilir.


0

GitHub kullanıcıları için bu benim için çalıştı:

  1. Değişikliği yapmak istediğiniz dal koruma kurallarında, Zorla zorlamaya izin ver seçeneğinin etkinleştirildiğinden emin olun
  2. git reset --hard <full_hash_of_commit_to_reset_to>
  3. git push --force

Bu, yerel makinenizdeki ve GitHub sunucunuzdaki şube geçmişini "düzeltir", ancak kötü işlemden bu yana bu dalı sunucu ile eşitleyen herkes yerel makinelerinde geçmişe sahip olacaktır. Şubeye doğrudan itme izni varsa, bu taahhütler senkronize edildiğinde hemen yedeklenir.

Diğer herkesin yapması gereken, git resetyerel makinedeki şubeyi "düzeltmek" için yukarıdaki komuttur. Tabii ki , hedef karmadan sonra bu şubeye yapılan tüm yerel taahhütlere karşı dikkatli olmaları gerekir . Kirazları gerektiği gibi toplayın / yedekleyin ve yeniden uygulayın, ancak korunan bir şubedeyseniz, doğrudan taahhütte bulunabilecek kişi sayısı muhtemelen sınırlıdır.

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.