Чому Git каже, що моя головна галузь «уже оновлена», хоча вона не є?


118

Основна проблема

Я щойно видалив ВСІЙ код з файлу в своєму проекті і вчинив зміни в моєму локальному git (спеціально). я зробила

git pull upstream master

для отримання та злиття з висхідного потоку (так теоретично, що видалений код повинен бути повернутий).

Git каже мені, що все актуально.

Все напевно НЕ актуально - весь цей видалений код все ще видаляється.

Інша відповідна інформація

У мене є лише одна гілка під назвою "господар".

Нещодавно я створив "майстра" для відстеження вгору за течією:

Мастер відділення налаштовано для відстеження віддаленого ведучого відділення від верхнього потоку.

Команда git branch -vvдає:

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

Чому чому так відбувається? Мені доводиться просто надсилати електронному листу моєму менеджеру проектів будь-які зміни, внесені до нашого коду.

Оновлення

Я думав, що це очевидно, але все одно це моя мета:

Отримайте найсвіжіший код у моїй системі.

Вибачте тут свій гнів, але чому таке просте завдання, як це, повинно бути таким важким?


1
Очевидно, що якщо ви видалите своє джерело, то спробуйте потягнути прямолінійним "потягнутим", що git не змінить ваші локальні зміни (у цьому випадку ваші вилучення), не гарантуючи, що ви дійсно хочете змінити локальні зміни. Перша відповідь, здається, пояснює, як саме ви можете це зробити.
CashCow

Відповіді:


209

Я думаю, що ваша основна проблема тут полягає в тому, що ви неправильно трактуєте та / або нерозумієте, що робить git і чому це робить.

Коли ви клонуєте якесь інше сховище, git робить копію всього, що там "там". Він також приймає "їх" ярлики гілок, таких як master, і робить копію тієї мітки, "повне ім'я" у вашому дереві git є (як правило) remotes/origin/master(але у вашому випадку, remotes/upstream/master). У більшості випадків ви також опускаєте remotes/частину, тому ви можете посилатися на цю оригінальну копію як upstream/master.

Якщо тепер внести і внести деякі зміни (файли) в який-небудь файл (и), ти єдиний із цими змінами. Тим часом інші люди можуть використовувати оригінальний сховище (з якого ви зробили свій клон), щоб зробити інші клони та змінити їх. Вони, звичайно, єдині зі своїми змінами. Зрештою, у когось можуть бути зміни, які вони надсилають назад первинному власнику (за допомогою "push", патчів чи будь-чого іншого).

git pullКоманда в основному тільки обраховувати для git fetchподальшої git merge. Це важливо, оскільки це означає, що вам потрібно зрозуміти, що насправді роблять ці дві операції.

git fetchКоманда каже , щоб повернутися туди , де ви клонували з (або в іншому випадку встановити в якості місця для вилучення з) і знайти «новий матеріал хто - то додали або змінені або видалені». Ці зміни копіюються та застосовуються до вашої копії того, що ви отримали від них раніше . Вони не застосовуються до вашої власної роботи, лише до їхньої роботи.

git mergeКоманда складніша і де ви збираєтеся наперекосяк. Що це робиться, трохи спрощено, це порівняти "те, що ви змінили в своїй копії", "зміни, які ви отримали від когось іншого, і таким чином додали до вашої роботи" копія-чи-то-кого-небудь ". Якщо ваші зміни та їх зміни, здається, не суперечать, mergeоперація з'єднує їх і дає вам "злиття", яке пов'язує ваш розвиток та їх розвиток разом (хоча є дуже поширений "легкий" випадок, у якому у вас немає змінюється, і ви отримуєте "швидкий вперед").

Ситуація Ви стикаєтеся зараз один , в якому були внесені зміни та скоїв їх дев'ять разів, справді, отже, «попереду 9» -І вони не зробили ні одного зміни. Отже, fetchслухняно витягує нічого, а потім mergeприймає їх нестачу змін, а також нічого не робить.

Те, що ви хочете, - це подивитися, а може, навіть "скинути" на "їх" версію коду.

Якщо ви просто хочете подивитися, ви можете просто перевірити цю версію:

git checkout upstream/master

Це вказує git, що ви хочете перемістити поточний каталог у гілку, повна назва якої є насправді remotes/upstream/master. Ви побачите їх код станом на останній раз, коли ви запустили git fetchта отримали останній код.

Якщо ви хочете відмовитися від усіх власних змін, то вам потрібно змінити ідею git про те, що переглядати ваш ярлик,, masterслід назвати. В даний час він називає ваші найсвіжіші коміти. Якщо ви повернетесь до цієї гілки:

git checkout master

тоді git resetкоманда дозволить вам "перемістити мітку", як би там не було. Єдина проблема, що залишилася (якщо припустити, що ви справді готові відмовитися від усього, що ви робите) - це пошук місця, куди повинна вказувати мітка.

git logдозволить вам знайти числові імена - такі речі, як 7cfcb29- які є постійними (ніколи не змінюються) іменами, і є безглузде число інших способів їх назви, але в цьому випадку ви просто хочете, щоб ім'я upstream/master.

Щоб перемістити мітку, знищивши свої зміни (ті , які ви зробили фактично відшкодовано досить довгий час , але це набагато складніше після того, як це так бути дуже впевнений):

git reset --hard upstream/master

--hardРозповідає мерзотник , щоб знищити те , що ви робите, перемістити поточну мітку гілки, а потім перевірити дане зобов'язання.

Це не надто звичайно, щоб дійсно захотіти git reset --hardі знищити купу роботи. Більш безпечний метод (полегшити відновлення роботи, якщо ви вирішите, що все-таки варто було зрештою) - перейменувати існуючу галузь:

git branch -m master bunchofhacks

а потім складіть нову локальну гілку з назвою master"треки" (мені не дуже подобається цей термін, оскільки я думаю, що він бентежить людей, але це термін git :-)) походження (або вище) майстер:

git branch -t master upstream/master

яку ви можете потім набути на себе:

git checkout master

Те, що роблять останні три команди (є ярлики, щоб зробити це лише двома командами), - це змінити ім'я, вставлене на існуючу мітку, а потім зробити нову мітку, а потім перейти до неї:

перш ніж робити що-небудь:

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

після git branch -m:

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

після git branch -t master upstream/master:

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

Ось C0остання фіксація (повне дерево джерела), яку ви отримали, коли ви вперше зробили своє git clone. Від C1 до C9 - це ваші зобов'язання.

Зауважте, що якби ви git checkout bunchofhacksі тоді git reset --hard HEAD^^, це змінило б останню картину на:

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

Причина полягає в тому, що називається HEAD^^редакція дві вгору від голови поточної гілки (що безпосередньо до скидання буде bunchofhacks), а reset --hardпотім переміщує мітку. Коміти C8 і C9 в основному невидимі (ви можете використовувати такі речі, як рефлог, і git fsckзнаходити їх, але це вже не банально). Ваші етикетки ваші, щоб рухатись, як завгодно. fetchКоманда піклується про тих , які починаються з remotes/. Це звичайне співставлення "ваше" з "їхнім" (тому, якщо вони мають remotes/origin/mauveназву і вашого mauve), але ви можете вводити "їх", коли ви хочете назвати / побачити комісії, які ви отримали "від них". (Пам'ятайте, що "одна фіксація" - це ціле дерево джерела. Ви можете вибрати один конкретний файл з одного коміту, git showнаприклад,


12
Я багато чого навчився з вашої чудової відповіді. Але я все ще плутаюсь щодо того, чому я отримую повідомлення про статус git: "Ваша гілка оновлюється" origin / master "", коли репо-версія на кілька потоків перевершує мою поточну репо. Я можу бути в курсі потягу git, але як я знаю, що мені потрібно це робити, якщо в повідомленні написано, що я в курсі останніх?
Крістофер Вербі

@ChristopherWerby: це здається, що ти працюєш git mergeяк командний рядок (це я щось роблю сам, це розумний метод). Зверніть увагу, що це git pullпочинається спочатку запуском git fetch, а потім запуском git merge(або git rebaseякщо ви скажете це зробити замість цього). Це крок вибору, який насправді приносить нові об'єкти, що підлягають об'єднанню (або лише на основі базування).
torek

@torek Чи є якась інша команда, ніж git statusя, яку я можу використати, щоб побачити, чи репост вище в потоці попереду мого поточного репо? Повідомлення, яке я отримую з git statusцього питання, говорить про те, що "Ваша філія оновлюється" походженням / господарем "" заплутує мене в думці, що у мене є останні зміни, коли я цього не роблю. Іноді я отримую повідомлення, в якому сказано щось на кшталт "походження / майстер на 5 комірок попереду вашої гілки" (перефразування). Але це не послідовно.
Крістофер Вербі

1
Це насправді не відповідає, чому git statusкажуть "Ваша гілка оновлена", коли негайно git fetchзнімає понад сто об'єктів і вирішує майже сто дельт, згадує кілька нових гілок та пару нових тегів та змінює головне (віддалене відстеження) керівник відділення здійснює - а потім ще один статус git весело та наполегливо все ще каже "Ваша філія актуальна". Зрозуміло, що багато походить від походження, але галузь "була в курсі походження" до і після?
NeilG

1
git pullзапускається git fetchспочатку, потім git merge(або інша друга команда на ваш вибір). Цей git fetchкрок оновлює пам’ять вашого Git про стан їх Git, викликаючи їх Git і отримуючи від них все нове. Ви git statusлише перевіряєте пам'ять свого Git у Git.
Торека

18

У мене була така ж проблема, як у вас.

Я так і зробив git status git fetch git pull, але моє відділення все ще відстало від походження. У мене папки та файли були висунуті на віддалене місце, і я бачив файли в Інтернеті, але в моїх локальних вони відсутні.

Нарешті, ці команди оновили всі файли та папки в моєму локальному:

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

або якщо ви хочете відділення

git checkout your_branch_name_here
git reset --hard origin/your_branch_name_here

1
Дякую! це фактично спрацювало. Майте на увазі, що назви філій залежать від регістру!
Андре Рамон

4

Будь-які зміни, які ви здійснили, як-от видалення всіх файлів проекту, все одно відбудуться після витягування. Все, що полягає в об'єднанні, - це об'єднання останніх змін з іншого місця у вашу власну гілку, і якщо ваша філія видалила все, то в кращому випадку ви отримаєте конфлікти злиття, коли зміни вгорі зачіпають файли, які ви видалили. Отже, коротше, так, все актуально.

Якщо ви опишете, який результат ви хотіли б мати замість "всі файли видалені", можливо, хтось може запропонувати відповідний спосіб дії.

Оновлення:

ВИДАЙТЕ НАЙБІЛЬШИЙ КОД КОДУ НА МОЮ СИСТЕМУ

Здається, ви, здається, не розумієте, що у вас вже є останній код, який є вашим. Якщо ви дійсно хочете, щоб побачити останню з чужих робіт, що знаходяться на головній гілці, просто зробіть:

git fetch upstream
git checkout upstream/master

Зауважте, що це не дозволить вам негайно (повторно) розпочати власну роботу. Якщо вам потрібно знати, як скасувати щось, що ви зробили або іншим чином відновити зміни, зроблені вами чи ким-небудь іншим, то, будь ласка, надайте деталі. Крім того, подумайте про ознайомлення з тим, для чого призначений контроль версій, оскільки ви, здається, неправильно розумієте його основне призначення.


Насправді я хочу останню версію чужого коду в моїй системі. Однак ці дві команди цього не зробили. Все, що я отримую, - це вже «майстер відділення». Код у моїх файлах не відображає код іншої людини.
user1971506

Вибачте, мав би бути upstream/master. Оновлено мою відповідь.
Райан Стюарт

3

Як кажуть інші афіші, перетягніть зміни злиття з верхнього потоку у ваше сховище. Якщо ви хочете замінити те, що є у вашому сховищі, на те, що знаходиться у потоці, у вас є кілька варіантів. З манжети я б пішов

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

Найвища відповідь набагато краща з точки зору широти та глибини поданої інформації, але, схоже, якби ви хотіли, щоб ваша проблема була виправлена ​​майже негайно, і не заперечуйте над тим, щоб натрапити на деякі основні принципи контролю версій, ви могли б ...

  1. Переключитися на головного

    $ git checkout upstream master
    
  2. Видаліть небажану гілку. (Примітка: він повинен мати -D, а не звичайний прапор -d, тому що у вашої гілки багато комісій перед майстром.)

    $ git branch -d <branch_name>
    
  3. Створіть нове відділення

    $ git checkout -b <new_branch_name>
    

1

Хоча жодна з цих відповідей не працювала для мене, я зміг виправити проблему за допомогою наступної команди.

git fetch origin

Це зробило для мене хитрість.


0

Просто дружнє нагадування, якщо у вас є локальні файли, яких немає в Github, і все-таки ви git statusговорите

Ваше відділення в курсі "походження / майстра". нічого не вчинити, працюючи дерево чисто

Це може статися, якщо файли є .gitignore

Спробуйте запустити

cat .gitignore 

і побачити, чи з’являються ці файли там. Це пояснило б, чому git не хоче переміщати їх у віддалений.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.