Acho que seu problema básico aqui é que você está interpretando mal e / ou entendendo mal o que o git faz e por que o faz.
Quando você clona algum outro repositório, o git faz uma cópia de tudo o que está "ali". Ele também pega "seus" rótulos de branch, como master
, e faz uma cópia desse rótulo cujo "nome completo" em sua árvore git é (normalmente) remotes/origin/master
(mas no seu caso, remotes/upstream/master
). Na maioria das vezes, você também pode omitir a remotes/
parte, então pode se referir a essa cópia original como upstream/master
.
Se você agora fizer e enviar algumas alterações em algum (s) arquivo (s), você é o único com essas alterações. Enquanto isso, outras pessoas podem usar o repositório original (do qual você fez o seu clone) para fazer outros clones e alterar esses clones. Eles são os únicos com suas mudanças, é claro. Porém, eventualmente, alguém pode ter alterações que enviará de volta ao proprietário original (via "push" ou patches ou qualquer outro).
O git pull
comando é basicamente uma abreviação de git fetch
seguido de git merge
. Isso é importante porque significa que você precisa entender o que essas duas operações realmente fazem.
O git fetch
comando diz para voltar ao local de onde você clonou (ou configurou como um lugar de onde buscar) e encontrar "coisas novas que outra pessoa adicionou, alterou ou removeu". Essas alterações são copiadas e aplicadas à sua cópia do que você obteve antes . Eles não se aplicam ao seu próprio trabalho, apenas ao deles.
O git merge
comando é mais complicado e é onde você está errando. O que ele faz, simplificando um pouco, é comparar "o que você alterou em sua cópia" com "alterações que você obteve de outra pessoa e, portanto, foi adicionado à sua cópia do trabalho de outra pessoa". Se suas mudanças e suas mudanças não parecem entrar em conflito, a merge
operação os junta e dá a você um "commit de mesclagem" que une seu desenvolvimento e o desenvolvimento deles (embora haja um caso "fácil" muito comum no qual você não tem muda e você obtém um "avanço rápido").
A situação que você está enfrentando agora é aquele em que você tiver feito alterações e os entregou-nove vezes, de fato, daí o "na frente por 9" -e eles fizeram há mudanças. Portanto, fetch
obedientemente não busca nada, e então merge
pega a falta de mudanças e também não faz nada.
O que você quer é examinar, ou talvez até "redefinir" para a versão "deles" do código.
Se você deseja apenas dar uma olhada, pode simplesmente verificar essa versão:
git checkout upstream/master
Isso diz ao git que você deseja mover o diretório atual para o branch cujo nome completo é na verdade remotes/upstream/master
. Você verá o código da última vez em que executou git fetch
e obteve o código mais recente.
Se você quiser abandonar todas as suas próprias mudanças, o que você precisa fazer é mudar a ideia do git de qual revisão seu rótulo,, master
deve nomear. Atualmente, ele nomeia seu commit mais recente. Se você voltar para aquele galho:
git checkout master
então o git reset
comando permitirá que você "mova o rótulo", por assim dizer. O único problema restante (assumindo que você está realmente pronto para abandonar tudo o que você vestiu) é descobrir onde o rótulo deve apontar.
git log
permitirá que você encontre os nomes numéricos - coisas como 7cfcb29
- que são nomes permanentes (nunca mudam), e há um número ridículo de outras maneiras de nomeá-los, mas neste caso você só quer o nome upstream/master
.
Para mover o rótulo, acabando com suas próprias mudanças (qualquer que você cometeu são realmente recuperável por um bom tempo, mas é muito mais difícil após este assim que seja muito certo):
git reset --hard upstream/master
O --hard
comando diz ao git para apagar o que você tem feito, mover o rótulo do branch atual e então verificar o commit fornecido.
Não é muito comum querer realmentegit reset --hard
e acabar com um monte de trabalho. Um método mais seguro (tornando muito mais fácil recuperar esse trabalho se você decidir que algo valeu a pena afinal) é renomear seu branch existente:
git branch -m master bunchofhacks
e então fazer um novo branch local chamado master
"tracks" (eu realmente não gosto deste termo porque acho que confunde as pessoas, mas esse é o termo git :-)) o mestre de origem (ou upstream):
git branch -t master upstream/master
que você pode fazer com:
git checkout master
O que os três últimos comandos fazem (há atalhos para torná-los apenas dois comandos) é alterar o nome colado no rótulo existente, criar um novo rótulo e, em seguida, alternar para ele:
antes de fazer qualquer coisa:
C0 - "remotes/upstream/master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "master"
depois git branch -m
:
C0 - "remotes/upstream/master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "bunchofhacks"
depois git branch -t master upstream/master
:
C0 - "remotes/upstream/master", "master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9 "bunchofhacks"
Aqui C0
está o último commit (uma árvore de código-fonte completa) que você obteve quando fez o seu git clone
. C1 a C9 são seus commits.
Observe que se você fosse git checkout bunchofhacks
e então git reset --hard HEAD^^
, isso mudaria a última imagem para:
C0 - "remotes/upstream/master", "master"
\
\- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 - "bunchofhacks"
\
\- C8 --- C9
A razão é que HEAD^^
nomeia a revisão dois acima do cabeçalho do branch atual (o que seria um pouco antes da redefinição bunchofhacks
) e, em reset --hard
seguida, move o rótulo. Os commits C8 e C9 agora são quase invisíveis (você pode usar coisas como o reflog e git fsck
encontrá-los, mas não é mais trivial). Seus rótulos são seus para mover como quiser. O fetch
comando cuida daqueles que começam com remotes/
. É convencional combinar "seu" com "deles" (então, se eles tiverem um, remotes/origin/mauve
você também deve nomear o seu mauve
), mas você pode digitar "deles" sempre que quiser nomear / ver os commits que obteve "deles". (Lembre-se de que "um commit" é uma árvore de origem inteira. Você pode escolher um arquivo específico de um commit, com, git show
por exemplo,