Por que o git continua mostrando minhas mudanças quando eu troco de branch (arquivos modificados, adicionados, excluídos), não importa se eu executo git add ou não?

115

Eu sou realmente novo no git e estou tentando entender por que o git continua mostrando tudo o que eu mudei em um branch em outro branch quando executei git checkout para alternar entre os branches. Primeiro, tentei não usar git add e não funcionou. No entanto, tentei usar git add, mas não resolvi o problema. Não estou usando o git commit ainda.

Isso é basicamente o que estou fazendo:

$ git clone <a_repository>  
$ git branch  
* master  
$ git branch testing  
$ git checkout testing  
...edit a file, add a new one, delete...  
$ git status  
    # On branch testing  
    # Changed but not updated:  
    #   (use "git add/rm <file>..." to update what will be committed)  
    #   (use "git checkout -- <file>..." to discard changes in working directory)  
    #  
    #       deleted:    file1.txt  
    #  
    # Untracked files:  
    #   (use "git add <file>..." to include in what will be committed)  
    #  
    #       file2.txt  
no changes added to commit (use "git add" and/or "git commit -a")  
$ git branch  
  master  
* testing  
$ git checkout master  
D       file1.txt  
Switched to branch 'master'  
$ git status  
    # On branch master  
    # Changed but not updated:  
    #   (use "git add/rm <file>..." to update what will be committed)  
    #   (use "git checkout -- <file>..." to discard changes in working directory)  
    #  
    #       deleted:    file1.txt  
    #  
    # Untracked files:  
    #   (use "git add <file>..." to include in what will be committed)  
    #  
    #       file2.txt  
no changes added to commit (use "git add" and/or "git commit -a")  

Eu pensei que, ao usar ramos, tudo o que você faz em um ramo, é invisível para todos os outros ramos. Não é por isso que se criam ramos?

Tentei usar "git add", mas as alterações são visíveis em ambos os ramos. Preciso executar "git commit" antes de alternar entre branches para evitar isso?

JPZ
fonte

Respostas:

142

A troca de ramos traz consigo mudanças não confirmadas. Faça commit primeiro, execute git checkout .para desfazê-los ou execute git stashantes de alternar. (Você pode obter suas alterações de volta com git stash apply)

Sean Clark Hess
fonte
10
git stash pop é melhor, a menos que você queira construir uma enorme pilha de stashes.
siride,
7
@JPZ: git stash lida apenas com arquivos rastreados; novos arquivos não são rastreados, portanto, não serão armazenados.
siride,
2
@JPZ: Se você quiser esconder arquivos não rastreados, a única coisa a fazer são git addeles antes de guardá-los. Dito isso, não tenho certeza se você realmente deseja esconder aqui - se você pretende que essas alterações façam parte do branch do qual você está mudando, envie-as. (Se você pretende voltar para aquele branch e trabalhar mais nas alterações antes de confirmá-las, então stashpode ser a ferramenta certa para o trabalho.)
Cascabel
16
"Alternar ramos carrega mudanças não comprometidas com você" - Isso faz sentido e talvez seja a pior ideia de design. De que adianta ter filiais se você não pode trabalhar de maneira isolada? !!!
nehem
1
No meu caso, tenho um branch de recurso de um branch de desenvolvimento. Eu me comprometi no branch de recursos, mas ele mostra as mudanças quando eu faço checkout no branch de desenvolvimento também.
Hitesh Garg
31

Resposta curta: sim, você precisa se comprometer. No entanto, certifique-se de fazer isso no branch certo!

Um branch é um ponteiro para um commit. Quando você efetua um commit com um branch em check-out, o branch avança para apontar para aquele novo commit. Quando você verifica um branch, está verificando o commit para o qual ele aponta. (Você pode pensar em commits como instantâneos de sua árvore de trabalho.)

Então, se você tem mudanças que não confirmou, elas não serão afetadas pela troca de branches. Claro, se a troca de branches for incompatível com suas alterações, git checkoutvocê simplesmente se recusará a fazê-lo.

git addé um comando para preparar mudanças, que você então enviará. Ele não registra essas mudanças no histórico do repositório. Ele simplesmente os coloca em uma área de teste (o índice); git commitem seguida, usa o conteúdo dessa área de teste para criar commits.

Cascabel
fonte