Ответ 1
Я думаю, что ваша основная проблема здесь в том, что вы неверно истолковываете и/или недопонимаете, что делает git и почему он это делает.
Когда вы клонируете какой-то другой репозиторий, git делает копию того, что там "там". Он также принимает "свои" метки ярлыков, такие как master
, и создает копию этого ярлыка, чье "полное имя" в вашем дереве git (обычно) remotes/origin/master
(но в вашем случае remotes/upstream/master
)), Большую часть времени вы также можете опустить часть remotes/
, чтобы вы могли ссылаться на эту оригинальную копию как upstream/master
.
Если вы сейчас внесете и внесете некоторые изменения в некоторые файлы (ы), вы будете единственными с этими изменениями. Тем временем другие люди могут использовать оригинальный репозиторий (из которого вы сделали свой клон), чтобы сделать другие клоны и изменить эти клоны. Конечно, они единственные с их изменениями. В конце концов, хотя у кого-то могут быть изменения, они отправляются обратно первоначальному владельцу (через "push" или patches или что-то еще).
Команда git pull
в основном просто сокращается для git fetch
, за которой следует git merge
. Это важно, потому что это означает, что вам нужно понять, что делают эти две операции.
Команда git fetch
говорит о том, чтобы вернуться туда, где вы клонировали (или иначе настроили место для извлечения), и найти "новые вещи, которые кто-то добавил, изменил или удалил". Эти изменения копируются и применяются к вашей копии того, что вы получили от них ранее. Они не применяются к вашей собственной работе, только к их.
Команда git merge
более сложна, и там, где вы ошибетесь. То, что он делает, немного упрощает, сравнивает "то, что вы изменили в своей копии", чтобы "меняли вы кого-то другого" и, таким образом, были добавлены в вашу "копию-из-за-кого-то". Если ваши изменения и их изменения, похоже, не конфликтуют, операция merge
объединяет их вместе и дает вам "фиксацию слияния", которая связывает ваше развитие и их развитие вместе (хотя существует очень распространенный "простой" случай, когда у вас нет изменений, и вы получаете "быструю перемотку вперед" ).
Ситуация, с которой вы сталкиваетесь сейчас, - это та, в которой вы внесли изменения и совершили их - девять раз, по сути, отсюда "впереди 9", и они не внесли никаких изменений. Итак, fetch
покорно ничего не получает, а затем merge
принимает свои недостатки-изменения и ничего не делает.
Вы хотите посмотреть или, возможно, даже "reset" на "свою" версию кода.
Если вы просто хотите посмотреть на него, вы можете просто проверить эту версию:
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 уничтожить то, что вы делали, переместите текущую метку ветки и затем проверите данную фиксацию.
Это не супер-общее, чтобы действительно хотеть 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
. С1 по С9 - ваши коммиты.
Обратите внимание, что если бы вы были git checkout bunchofhacks
, а затем git reset --hard HEAD^^
, это изменило бы последнее изображение на:
C0 - "remotes/upstream/master", "master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 - "bunchofhacks"
\
\- C8 --- C9
Причина в том, что HEAD^^
называет ревизию два от главы текущей ветки (которая непосредственно перед reset будет bunchofhacks
), а reset --hard
затем перемещает метку. Commits C8 и C9 теперь в основном невидимы (вы можете использовать такие вещи, как reflog и git fsck
, чтобы найти их, но это уже не тривиально). Ваши ярлыки ваши, чтобы двигаться, как вам нравится. Команда fetch
заботится о тех, которые начинаются с remotes/
. Это условно, чтобы соответствовать "вашим" с "их" (так что если у них есть remotes/origin/mauve
, вы бы назвали ваш mauve
тоже), но вы можете набирать "их", когда хотите называть/видеть, что у вас есть "от них". (Помните, что "одно коммит" является целым деревом источника. Вы можете выбрать один конкретный файл из одного коммита с помощью git show
, например, если и когда вы этого хотите.)