Git neden olmasa da ana dalımın "zaten güncel" olduğunu söylüyor?


118

Temel Problem

Projemdeki bir dosyadan TÜM kodu sildim ve değişikliği yerel gitime (kasıtlı olarak) taahhüt ettim. yaptım

git pull upstream master

yukarı akıştan getirmek ve birleştirmek için (teoride silinen kodun geri gelmesi gerekir).

Git bana her şeyin güncel olduğunu söylüyor.

Her şey kesinlikle güncel DEĞİLDİR - silinen tüm kodlar hala silinmiştir.

Diğer İlgili Bilgiler

Yalnızca "usta" adında bir şubem var.

Yakın zamanda yukarı akışı izlemek için "ana" kurdum:

Şube yöneticisi, yukarı akıştan uzak şube yöneticisini izlemek için ayarlandı.

Komut şunu git branch -vvverir:

* master 7cfcb29 [upstream/master: ahead 9] deletion test

Neden bu neden oluyor? Kodumuzda yaptığım değişiklikleri proje yöneticime e-posta ile göndermenin eşiğindeyim.

Güncelleme

Bunun apaçık olduğunu düşünmüştüm, ama yine de amacım bu:

Sistemimdeki en son kodu alın.

Öfkemi burada mazur görün, ama neden bu kadar basit bir görev bu kadar zor olmak zorunda?


1
Kaynağınızı silerseniz, yerel değişikliklerinizi gerçekten geçersiz kılmak istediğinizden emin olmadan git'in yerel değişikliklerinizi (bu durumda silmelerinizi) geçersiz kılmayacağını basit bir "çekme" ile çekmeyi deneyin. İlk cevap, bunu tam olarak nasıl yapabileceğinizi açıklıyor gibi görünüyor.
CashCow

Yanıtlar:


209

Sanırım buradaki temel sorununuz git'in ne yaptığını ve neden yaptığını yanlış yorumlamanız ve / veya yanlış anlamanızdır.

Başka bir depoyu klonladığınızda git, "orada" olanın bir kopyasını oluşturur. Aynı zamanda gibi "kendi" şube etiketleri alır masterve "tam adı" bu etiketle bir kopyasını yapar senin git ağacından (normalde) 'dir remotes/origin/master(ama senin durumunda, içinde remotes/upstream/master). Çoğu zaman remotes/parçayı da atlarsınız , böylece orijinal kopyaya olarak bakabilirsiniz upstream/master.

Şimdi bazı dosyalarda bazı değişiklikler yapar ve taahhüt ederseniz, bu değişiklikleri yapan tek kişi sizsiniz. Bu arada, diğer insanlar, diğer klonları yapmak ve bu klonları değiştirmek için orijinal depoyu (sizin klonunuzu yaptığınız) kullanabilir. Elbette, değişiklikleri olan sadece onlar. Sonunda, bir kişinin orijinal sahibine geri gönderdiği değişiklikler olabilir ("push" veya yamalar veya her neyse).

git pullİçin komut çoğunlukla sadece steno edilir git fetchizledi git merge. Bu önemlidir çünkü bu iki işlemin gerçekte ne yaptığını anlamanız gerektiği anlamına gelir.

git fetchKomutu klonlanmış (veya başka türlü alınamayacak bir yer olarak kurdunuz) ve "yeni şeyler başkasının eklenen veya değiştirilen veya kaldırılan" bulduğunuz yerde dönmek söylüyor. Bu değişiklikler kopyalanır ve daha önce onlardan aldığınız kopyaya uygulanır . Onlar edilir değil sadece onların için, kendi çalışmalarına başvurmuştur.

git mergeKomut daha karmaşık ve ters nereye mesafesindedir. Biraz basitleştirilmiş olarak yaptığı şey, "kopyanızda değiştirdikleriniz" ile "başka birinden aldığınız ve böylece başkasının-çalışmasının-kopyasına-eklediğiniz değişiklikler" ile karşılaştırmaktır. Değişiklikleriniz ve değişiklikleri birbiriyle mergeçelişmiyor gibi görünüyorsa, işlem onları bir araya getirir ve size gelişiminizi ve gelişiminizi birbirine bağlayan bir "birleştirme taahhüdü" verir (yine de, sahip olmadığınız çok yaygın "kolay" bir durum vardır. değişir ve bir "ileri sar" alırsınız).

Şu anda karşılaştığınız durum, değişiklikler yaptığınız ve bunları yaptığınız bir durumdur - aslında dokuz kez, dolayısıyla "önde 9" ve hiçbir değişiklik yapmamışlardır . Yani, görev fetchbilinciyle hiçbir şey mergegetirmez ve sonra onların değişim eksikliklerini alır ve hiçbir şey yapmaz.

İstediğiniz şey, kodun "kendi" sürümüne bakmak, hatta belki "sıfırlamak".

Yalnızca bakmak istiyorsanız, o sürüme göz atabilirsiniz:

git checkout upstream/master

Bu, git'e geçerli dizini tam adı gerçekte olan şubeye taşımak istediğinizi söyler remotes/upstream/master. Kodlarını, en son koştuğunuz git fetchve en son kodlarını aldığınız andan itibaren göreceksiniz .

Tüm değişikliklerinizden vazgeçmek istiyorsanız , yapmanız gereken şey git'in etiketinizin hangi revizyonu masteradlandırması gerektiği konusundaki fikrini değiştirmektir . Şu anda en son yaptığınız işin adını veriyor. O şubeye geri dönersen:

git checkout master

Sonra git resetsanki komut, siz "etiketini taşımak" sağlayacaktır. Geriye kalan tek sorun (yaptığınız her şeyi terk etmeye gerçekten hazır olduğunuzu varsayarsak) etiketin nereye işaret etmesi gerektiğini bulmaktır.

git log7cfcb29kalıcı (asla değişmeyen) isimler olan sayısal isimleri bulmana izin verir ve bunları isimlendirmenin çok saçma sayıda başka yolu vardır, ama bu durumda sadece ismi istiyorsun upstream/master.

Etiketi taşımak için, kendi değişikliklerinizi silin (yaptığınız herhangi bir değişiklik aslında bir süredir kurtarılabilir, ancak bundan sonra çok daha zordur, bu yüzden çok emin olun):

git reset --hard upstream/master

--hardVerilen taahhüt kontrol o zaman, ne yaptığını silip şimdiki şube etiketini getirin ve git'e söyler.

Bir sürü işi gerçekten istemek git reset --hardve yok etmek çok yaygın değildir . Daha güvenli bir yöntem (sonuçta bir kısmının değerli olduğuna karar verirseniz, bu çalışmayı kurtarmayı çok daha kolay hale getirir) mevcut şubenizi yeniden adlandırmaktır:

git branch -m master bunchofhacks

ve sonra master"izler" adında yeni bir yerel şube oluşturun (bu terimi insanların kafasını karıştırdığını düşündüğüm için gerçekten sevmiyorum ama bu git terimi :-)) başlangıç ​​(veya yukarı akış) master:

git branch -t master upstream/master

daha sonra şunlarla başlayabilirsiniz:

git checkout master

Son üç komutun yaptığı şey (yalnızca iki komut yapmak için kısayollar vardır), mevcut etikete yapıştırılan adı değiştirmek, ardından yeni bir etiket oluşturmak ve sonra ona geçiş yapmaktır:

bir şey yapmadan önce:

C0 -    "remotes/upstream/master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "master"

sonra git branch -m:

C0 -    "remotes/upstream/master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "bunchofhacks"

sonra git branch -t master upstream/master:

C0 -    "remotes/upstream/master", "master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "bunchofhacks"

İşte C0, .tap'ınızı ilk yaptığınızda aldığınız en son commit (eksiksiz bir kaynak ağacı) git clone. C1 - C9 arası taahhütlerinizdir.

Olursa git checkout bunchofhacksve sonra git reset --hard HEAD^^, bunun son resmi şu şekilde değiştireceğini unutmayın:

C0 -    "remotes/upstream/master", "master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 -    "bunchofhacks"
                                                      \
                                                       \- C8 --- C9

Bunun nedeni, HEAD^^revizyonu geçerli dalın başından itibaren ikinci olarak adlandırması (sıfırlamadan hemen önce olacaktır bunchofhacks) ve reset --hardardından etiketi hareket ettirmesidir. C8 ve C9 işlemleri artık çoğunlukla görünmezdir (reflog gibi şeyleri ve git fsckonları bulmak için kullanabilirsiniz, ancak artık önemsiz değil). Etiketleriniz, istediğiniz gibi hareket etmeniz için sizindir. fetchKomut ile başlayan olanlar ilgilenir remotes/. "Sizinkini" "onların" ile eşleştirmek gelenekseldir (bu yüzden onlar da remotes/origin/mauvesizinki isminizi kullanırsanız mauve), ancak "onlardan" aldığınız taahhütleri adlandırmak / görmek istediğinizde "onların" adını yazabilirsiniz. ("Tek işlemenin" tüm kaynak ağacı olduğunu unutmayın. Tek bir işlemden belirli bir dosya seçebilirsiniz, git showörneğin,


12
Mükemmel cevabınızdan çok şey öğrendim. Ama yine de git durum mesajını neden aldığım konusunda kafam karıştı: "Şubeniz 'menşe / ana' ile günceldir", upstream repo mevcut repomun birkaç taahhütünden önce olduğunda. Git pull ile güncel bilgiler alabilirim, ancak mesajda güncel olduğumu söylüyorsa onu çekmem gerektiğini nasıl bilebilirim?
Christopher Werby

@ChristopherWerby: Kulağa git mergekomut satırı komutu olarak çalışıyormuşsunuz gibi geliyor (ki bu benim yaptığım bir şey, makul bir yöntem). Bununla birlikte, bunun git pullönce koşmakla git fetch, sonra koşmakla git merge(veya git rebasebunun yerine yapmasını söylerseniz) başladığını unutmayın. Bu, birleştirilecek (veya yalnızca yeniden ihraç edilecek) yeni taahhütleri gerçekten getiren getirme adımıdır.
torek

@torek Yukarı akış repo'sunun mevcut repomun git statusönünde olup olmadığını görmek için kullanabileceğim dışında bir komut var mı ? git statusAldığım "Şubeniz 'menşe / usta' ile günceldir" mesajı, beni, yapmadığım halde en son değişiklikleri aldığımı düşünmeye sevk ediyor. Bazen, "menşe / usta, şubenizden 5 taahhüt önde" gibi bir şey (başka kelimelerle ifade ederek) şeklinde bir mesaj alıyorum. Ama tutarlı değil.
Christopher Werby

1
Bu yine de git status, bir anda git fetchyüzün üzerinde nesneyi aşağı çekip neredeyse yüz deltayı çözdüğünde, birkaç yeni daldan ve birkaç yeni etiketten bahsedip ana izleme) şube başkanı commit - ve sonra başka bir git durumu neşeyle ve samimiyetsiz bir şekilde, hala "Şubeniz güncel" diyor. Açıkça çok şey kökeninden geldi ama şube hem öncesi hem de sonrası "menşeiyle güncel" miydi?
NeilG

1
git pullgit fetchönce çalışır , sonra git merge(veya seçtiğiniz diğer ikinci komut). git fetchAdım günceller senin GİT hafızasını onların yukarı arayarak seyahatseverlerin Git statüsü, onların Git ve onlardan yeni bir şey alma. Sizin git statussadece kendi Git senin seyahatseverlerin Git belleğini kontrol eder.
torek

18

Seninle aynı sorunu yaşadım.

Yaptım git status git fetch git pull, ama şubem hala kökeninin gerisindeydi. Uzaklara gönderilen klasörler ve dosyalarım vardı ve dosyaları web'de gördüm, ancak yerelimde eksiklerdi.

Son olarak, bu komutlar yerelimdeki tüm dosya ve klasörleri güncelledi:

git fetch --all
git reset --hard origin/master 

ya da bir dal istiyorsan

git checkout your_branch_name_here
git reset --hard origin/your_branch_name_here

1
Teşekkürler! bu gerçekten çalıştı. Şube adlarının büyük / küçük harfe duyarlı olduğunu unutmayın!
André Ramon

4

Tüm proje dosyalarınızı silmek gibi taahhüt ettiğiniz herhangi bir değişiklik, bir çekmeden sonra hala yerinde olacaktır. Çekmenin yaptığı tek şey, başka bir yerden en son değişiklikleri kendi şubenize birleştirmektir ve şubeniz her şeyi sildiyse, o zaman en iyi durumda, yukarı akış değişiklikleri sildiğiniz dosyaları etkilediğinde birleştirme çakışmaları alırsınız. Yani kısacası evet her şey güncel.

"Tüm dosyaların silinmesi" yerine hangi sonucu elde etmek istediğinizi açıklarsanız, belki birisi uygun bir hareket tarzı önerebilir.

Güncelleme:

SİSTEMİMDEKİ EN SON KODU ALIN

Anlayamadığın şey, en son koda sahip olduğun, ki bu senin. Gerçekten istediğiniz şey, başkasının ana daldaki en son çalışmasını görmekse, şunu yapın:

git fetch upstream
git checkout upstream/master

Bunun sizi kendi işinize hemen (yeniden) başlama konumunda bırakmayacağını unutmayın. Yaptığınız bir şeyi nasıl geri alacağınızı veya sizin veya başka birinin yaptığı değişiklikleri nasıl geri alacağınızı bilmeniz gerekiyorsa, lütfen ayrıntıları sağlayın. Ayrıca, temel amacını yanlış anladığınızdan, sürüm kontrolünün ne için olduğunu okumayı düşünün.


Aslında, sistemimde başka birinin kodunun en son sürümünü istiyorum. Ancak, bu iki komut bunu yapmadı. Tek aldığım "zaten şube yöneticisinde". Dosyalarımdaki kod, diğer kişinin kodunu yansıtmıyor.
user1971506

Üzgünüm, olmalıydı upstream/master. Cevabım güncellendi.
Ryan Stewart

3

Diğer posterlerin dediği gibi, yukarı akıştan deponuza değişiklikleri çek. Deponuzda olanı yukarı akışta olanla değiştirmek istiyorsanız, birkaç seçeneğiniz vardır. Manşetten çıkar, giderdim

git checkout HEAD^1  # Get off your repo's master.. doesn't matter where you go, so just go back one commit
git branch -d master  # Delete your repo's master branch
git checkout -t upstream/master  # Check out upstream's master into a local tracking branch of the same name

1

En iyi cevap, verilen bilginin genişliği ve derinliği açısından çok daha iyidir, ancak sorununuzun hemen çözülmesini istiyorsanız ve sürüm kontrolünün bazı temel ilkelerini denemeye aldırış etmiyorsanız, yapabilirsiniz ...

  1. Ustaya geç

    $ git checkout upstream master
    
  2. İstenmeyen şubenizi silin. (Not: normal -d bayrağının yerine -D'ye sahip olması gerekir, çünkü dalınız ana birimin önünde birçok işlemdir.)

    $ git branch -d <branch_name>
    
  3. Yeni bir şube oluştur

    $ git checkout -b <new_branch_name>
    

1

Bu yanıtların hiçbiri benim için işe yaramasa da, aşağıdaki komutu kullanarak sorunu çözebildim.

git fetch origin

Bu benim için bir numara yaptı.


0

Github olmayan dosyaları yerel olarak sahip ve henüz senin eğer Sadece dostça bir hatırlatma git statusdiyor

Şubeniz 'menşe / ana' ile güncel. işlenecek bir şey yok, ağaç temiz çalışıyor

Dosyalar içeride ise olabilir .gitignore

Koşmayı dene

cat .gitignore 

ve bu dosyaların orada görünüp görünmediğini görmek. Bu, git'in neden onları uzaktan kumandaya taşımak istemediğini açıklıyor.

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.