[Tutorial Git] git reset: Retirando arquivos da "sala de espera" e desfazendo commits
Tags: git, reset, braziliandevs
Published: 2020-06-03 17:40:59

## Atenção!

Esse comando é recomendado apenas para uso em arquivos locais, ou seja, para os arquivos que estão somente na sua máquina e não em um repositório remoto.


## Modo de usar o reset: padrão ou mixed

Esse comando pode ser usado para retirar arquivos do **index**(a "sala de espera" do git).

![arquivos no index](https://dev-to-uploads.s3.amazonaws.com/i/w9ahk8qrs1gq30f9g7ws.png)

Lembrando que os arquivos que estão no **index** são aqueles em que foram usados o comando **git add**, mas que ainda não receberam um **commit**.

[Clique aqui](https://dev.to/womakerscode/tutorial-git-adicionando-arquivos-no-git-3a0o), caso precise saber mais sobre o comando add do Git.

Sendo assim, usamos:

```
$ git reset <nome_do_arquivo>
```

- **$** indica que você deve usar o **usuário comum** para fazer essa operação.
- nome do arquivo sem os sinais **< e >**.

que tem o mesmo valor do comando

```
$ git reset --mixed <nome_do_arquivo>
```

Quando não é especificado o modo, o **Git** usarão o **padrão**, que é o **mixed**.

Exemplo:

Vamos supor que eu tenho, no meu projeto, um arquivo já **rastreado pelo Git**, mas que foi **modificado**.

![arquivo modificado](https://dev-to-uploads.s3.amazonaws.com/i/i9e6kbyu9a3iv24oihzr.png)

![fluxo do arquivo modificado](https://dev-to-uploads.s3.amazonaws.com/i/bdjgsbrb64p393pknr59.png)

E acabei mandando-o para o **index**

![arquivo no index](https://dev-to-uploads.s3.amazonaws.com/i/5uoj5womjs5tac5al63g.png)

![fluxo do arquivo no index](https://dev-to-uploads.s3.amazonaws.com/i/fuvphmlhj7q1838i7g02.png)

Entretanto, **não** era para esse arquivo estar no **index** pois ainda preciso fazer outras alterações nele.

Sendo assim, para retirá-lo, uso o comando

```
$ git reset comite_etica_inline.html
```

![retomando o arquivo para o working directory](https://dev-to-uploads.s3.amazonaws.com/i/ofa9ngjch3uz91hlm0xb.png)

![fluxo do arquivo retornando para o working directory](https://dev-to-uploads.s3.amazonaws.com/i/x5fu98lp17s13ktawu7t.png)


## Modo de usar o reset: soft

Esse modo de usar o comando reset serve apenas para alterar o ponteiro **head**:

```
$ git reset --soft <chave_do_commit>
```

> O **HEAD** é um ponteiro no branch que normalmente aponta para o último commit feito.

Exemplo:

Tenho os seguintes commits no meu projeto:

![retorno do comando git log](https://dev-to-uploads.s3.amazonaws.com/i/6sk6qnfazzuta8d77fnv.png)

![commits no fluxo do git](https://dev-to-uploads.s3.amazonaws.com/i/ox9nn9lwu1r0o47kvf1m.png)

![selecionando commit](https://dev-to-uploads.s3.amazonaws.com/i/4qsz0lu5t1mjhkb0u0yp.png)

Agora, atenção ao arquivo **comite_etica_inline.html** que estava na seguinte situação no **commit 669629**.

![arquivo no commit 669629](https://dev-to-uploads.s3.amazonaws.com/i/ytoapm5g9v51ieqcrhk2.png)

E passou para a situação abaixo no **commit 9e8cf9**

![commit 9e8cf9](https://dev-to-uploads.s3.amazonaws.com/i/whjkq322gvakiw3kqj91.png)

Vamos voltar o ponteiro **head** ao commit selecionado na imagem abaixo, pois pretendo **refazer os commits** que estão acima deste, sem de fato, mudar o projeto e tudo o que foi feito até agora.

![selecionando o commit](https://dev-to-uploads.s3.amazonaws.com/i/0kdtyeyfhkzjrh3cpb3i.png)

Sendo assim, fazemos

```
$ git reset --soft b240d3c43a
```

Verificando os **commits** é possível perceber o deslocamento do ponteiro **head** para onde queríamos.

![ponteiro head reposicionado](https://dev-to-uploads.s3.amazonaws.com/i/gpoqp79pa163o8zzolre.png)

Verificando o **estado do Git**, podemos ver que os dois arquivos que foram inseridos nos **commits** posteriores ao nosso **head atual** aparecem como novos arquivos no **index**.

![novos arquivos no index após o reset soft](https://dev-to-uploads.s3.amazonaws.com/i/rfqxghee8alyee6klw4r.png)

No log anterior (antes do **reset soft**), tínhamos

![commits onde os arquivos foram inseridos](https://dev-to-uploads.s3.amazonaws.com/i/c0atzp5o9itbkwobrp9p.png)

No fluxo atual do Git, temos

![fluxo do git após o reset soft](https://dev-to-uploads.s3.amazonaws.com/i/n6cy67jos4hjsucoctis.png)

Aqui é importante notar que o área **working directory** não foi alterada.

Ou seja, o arquivo **comite_etica_inline.html** não voltou a ter a parte que retiramos dele, embora tenhamos voltado a um **commit** anterior a essa retirada.

![arquivo não voltou ao estado anterior](https://dev-to-uploads.s3.amazonaws.com/i/809p7hsv6u79keu5dq7p.png)

Confirmando que o comando **reset --soft** não interfere no **working directory**.

E embora ele adicione os arquivos que receberam algum **commit** anteriormente ao **index**, se houver algum arquivo no **index** antes do comando **reset --soft**, esse arquivo é mantido.

Exemplo:

![exemplo de um arquivo no index antes do reset soft](https://dev-to-uploads.s3.amazonaws.com/i/vx6ee3b9sr681qr98pke.png)

Esse comando é muito usado quando você fez uma sequência de **commits** repetitivos ou com diversas e pequenas alterações que poderiam ser resumidas em um único **commit**.


## Modo de usar o reset: hard

A principal diferença entre os comandos **reset --soft** e **reset --hard** é a interferência no **working directory** e no **index**.

Esse comando é usado em casos em que você bagunçou o código e precisa desfazer tudo o que fez. Porém é preciso ter cuidado com esse ele, pois se você apagar algum dado que não tinha intenção corre o risco de não conseguir recuperá-lo.

Para usar o comando, digite

```
$ git reset --hard <chave_do_commit>
```

Exemplo:

Temos os seguintes arquivos no diretório de um projeto,

![arquivos do projeto](https://dev-to-uploads.s3.amazonaws.com/i/wbhs80rtabv52zcjnqvn.png)

Os **commits** feitos até agora são,

![commits do projeto](https://dev-to-uploads.s3.amazonaws.com/i/n9aznxg1dw3u4pm1km4g.png)

E temos um arquivo no **index**, esperando pelo **commit**.

![arquivo no index](https://dev-to-uploads.s3.amazonaws.com/i/4ddbbkj5660173z0dgxn.png)

Vamos deslocar o ponteiro **head** para o mesmo **commit** que usamos no exemplo anterior, porém agora usando a **flag hard**.

```
$ git reset --hard b240d3c43a
```

Como podemos ver, não temos mais os arquivos **comite_etica_inline.html**, **comite_etica.js** e **mobile.css**. E o **index** está vazio.

![após uso do reset hard](https://dev-to-uploads.s3.amazonaws.com/i/saua6dlbvhr56wf5yiup.png)

Sendo assim, podemos perceber que tanto o **working directory** quanto o **index** sofreram alterações.


## Usando o HEAD no lugar da chave do commit

É possível substituir a **chave de um commit**, nos três modos de usar o reset, pelo próprio ponteiro **head** e assim movê-lo para o **commit** desejado.

```
$ git reset --mixed HEAD~<n>
```

```
$ git reset --soft HEAD~<n>
```

```
$ git reset --hard HEAD~<n>
```

- substitua o **n** por um número (sem os sinais **< e >**) para indicar quantos **commits** atrás o ponteiro **head** precisa voltar.

Exemplo:

```
$ git reset HEAD~3
```

Voltei o ponteiro **head** para três **commits** anteriores ao meu último. 

> lembrando que, como não usei nenhuma flag nesse exemplo, o modo usado aqui foi o padrão, ou seja, o **mixed**.


## Resumo dos modos do reset

De maneira resumida, temos:

- **Soft**: altera o ponteiro **head**.
- **Mixed**: altera o ponteiro **head** e o **index**.
- **Hard**: altera o ponteiro **head**, o **index** e o **working directory**.

![resumo dos modos do reset](https://dev-to-uploads.s3.amazonaws.com/i/oc2f1nq8t0184efu0cn8.png)