Git para Ciência de Dados
Tags: git, data, datascience, github
Published: 2020-11-20 13:00:03

> *A foto de cima é do Yancy Min, do [Unplash](https://unsplash.com/photos/842ofHC6MaI?utm_source=unsplash&utm_medium=referral&utm_content=creditShareLink)*

Olá! Esse post é a minha estreia aqui e eu vou tentar deixar um pouco mais claro os conceitos de Git, o porquê que é bom de usar, as boas práticas que eu adoto no meu dia-a-dia e também alguns macetes pra você não ter problemas lá na frente - ou ter menos problemas, pelo menos. Eu to assumindo que você trabalha com Ciência de Dados, mas só pra tentar trazer alguns exemplos pra nossa realidade. Se você não é um DS, ainda acho que tem bastante coisa aqui pra aproveitar. Bora? :smile:

# O que é Git?

Pra colocar em uma frase: Git é uma ferramenta gratuita e de código aberto para controle de versão de código-fonte. O troço é tão relevante, que foi criado pelo Linus Torvalds, criador do Linux, justamente pra controlar as versões do *kernel*. Doido, né?

### O básico
O que isso significa é que ele vai gerenciar pra você cada modificação que você fizer no seu modelo, alguma variável nova que você está calculando, enfim, tudo o que for modificado vai ser controlado por ele, através de cópias e chaves. Se quiser ler as documentações mais a fundo depois, dá uma olhada no [site oficial](https://git-scm.com/).

Então imagina que você hoje tenha essa estrutura em uma pasta:

<pre>
notebooks/
├── meu_modelo_v1.ipynb     
├── meu_modelo_v2.ipynb
├── meu_modelo_v2_27062021.ipynb
├── meu_modelo_final.ipynb
├── meu_modelo_final2.ipynb
</pre>

E você vai passar a ter uma estrutura assim, quando começar a usar Git:

<pre>
notebooks/
├── meu_modelo.ipynb     
</pre>

Ué, mas que bruxaria é essa? 🧙

### Versões através de chaves

Com esse desenho lindo aqui em baixo (risos) eu tentei mostrar como fica o seu código ao longo do tempo, da direita pra esquerda. O que acontece é que cada versão do seu código vai ser copiada pelo Git e atribuída a uma chave identificadora única. Isso acontece toda vez que você salvar o seu trabalho, ou, quando você der um *commit* - eu vou explicar esse jargão um pouco mais pra frente.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hnp66ah6zz9cq5eozh4i.png)

### Qual a diferença entre Git e Github?

Se a gente controlar as versões do nosso trabalho localmente, isso já dá uma aliviada muito grande. Mas se a gente pensa em trabalhar em equipe ou até mesmo em não depender do nosso computador funcionando sempre, é muito importante que isso vá pra algum lugar na nuvem, em um *servidor remoto*, para que a gente possa acessar depois. O Github é esse lugar. 

Além de armazenar nosso código e arquivos, ele também possibilita a gente controlar algumas coisas através da sua interface gráfica, facilitando bastante o trabalho no dia-a-dia. Além do Github, existem outros servidores remotos de Git, como Gitlab e Bitbucket. Escolhi falar sobre o Github porque é gratuito, o mais popular e, na minha opinião, muito completo. 

# Trabalhando com Git no dia-a-dia

Dando um salto para o fluxo de trabalho, vamos falar um pouco agora sobre como a gente trabalha com Git no dia-a-dia. Essa é a parte mais densa dessa postagem, mas vamo junto que isso vai ser muito útil para você! 


> **_NOTA:_** Estou aqui partindo do pressuposto que você já baixou o Git na sua máquina e também tem uma conta no Github. Caso contrário, pesquise sobre como fazer e volte aqui depois!

### Estrutura do Git e comandos principais

Um pouco mais abaixo eu resolvi deixar mais uma obra de arte para tentar visualmente caminhar pelos comandos mais importantes - não todos - e até entender como e porque a gente usa eles. 

O primeiro e talvez mais frequente comando que você vai utilizar é o 

```sh
$ git status
``` 

Com ele, você consegue saber o que tá acontecendo na sua pasta. Quais arquivos você tá e não tá controlando, se a sua versão do código está atualizada de acordo com o seu repositório e assim por diante. Sempre que você quiser conferir se deu certo o que você fez, mande um `git status`.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/iwdks64pvy4rr4q1jpru.png)

Quando você fizer as modificações no seu código, você vai mandá-lo pra uma área de *staging*, que vai basicamente indicar pro Git que esse código é um arquivo que você quer controlar a versão. Você faz isso através do comando:

```sh
$ git add meu_arquivo.py
```

Assim, o `meu_arquivo.py` irá ser indexado para que entre no seu próximo *commit* realizado. Se você quiser mandar para a área de indexação todos os seus arquivos de uma vez, use um *wildcard*, como:

```sh
$ git add .
```

Mas tenha **cuidado**! É muito fácil mandar algum arquivo ou diretório indesejado utilizando um *wildcard*. Então depois de adicionar os arquivos para a indexação, lembre-se de rodar um `git status` para saber o que está sendo indexado para ser versionado, tá? 

Uma vez indexado, seu código poderá ser salvo no repositório local através do comando `commit`. Essa etapa também é super importante, pois aqui você terá a possibilidade de dar um resumo sobre quais foram as alterações feitas nessa nova versão do código, de uma forma breve e objetiva. Para isso, use o comando:

```sh
$ git commit -m "modelo com média de preços para treino"
```

O argumento `-m` possibilita que você escreva uma frase para representar esse *commit*. Essa parte é tão crítica, que existem alguns [posts](https://code.likeagirl.io/antes-e-depois-das-minhas-mensagens-de-commit-1ad8cc288d05) sobre como escrever uma boa mensagem no *commit*. 

Uma vez que seu repositório local conhece as modificações que foram indexadas para esse *commit*, ta na hora de "empurrar" isso pra nuvem, com o comando 

```sh
$ git push
```

Dependendo de como você estruturou sua conexão, isso pode mandar as modificações direto para o seu repositório no Github ou te pedir o login e senha. De todo modo, tá salvo!

Os comandos `checkout`, `pull` e `fetch` eu vou cobrir no próximo tópico.

### Aproveite sua IDE!

Se você tá acostumado a trabalhar em uma IDE ou Editor de Texto, aproveite as funcionalidades que eles trazem para controle de versão de código. No PyCharm, por exemplo, as linhas que você modifica, apaga ou adiciona, criam marcadores específicos, que te indicam o que foi feito ali em relação ao código original.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/wv1i7jcgjcsc8z9qqeyk.png)

Além disso, os arquivos modificados também ficam com cores diferentes. E não só você pode acompanhar visualmente as modificações, como também pode realizar *add*, *commit* e *push* com apenas alguns cliques. Eu gosto muito de fazer tudo em um lugar só, então vale muito a pena explorar isso. Confia! 🤞

# Trabalhando em equipe

Bom, agora que você já tem uma ideia de como controlar as versões do código, chegou a hora de falar um pouco sobre como você faz pra utilizar isso na vida real, trabalhando com mais pessoas. E não ache que porque você é o único Cientista de Dados do seu projeto você está sozinho nessa. 
**O seu eu do futuro também é o seu colega de trabalho**. Parece meio louco pensar nisso, mas se você passar alguns meses sem mexer com um projeto, vai ser muito difícil olhar pra trás e saber o que foi feito sem existir uma boa documentação e cuidado com o trabalho realizado. 

### Branches

Pensando em trabalhar com mais pessoas, é fundamental que exista um código principal e que sejam criadas versões espelhadas do seu projeto, para que você possa fazer quaisquer mudanças sem afetar o código principal. 

Pensando nisso, criou-se o conceito de *branch* (em inglês, galho de árvore), que são ramificações do código principal. Para criar uma *branch*, você pode utilizar a interface gráfica do Github, clicando onde estiver escrito *master* (ou *main*), como mostra a figura:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hpbe0s2h5hsrjwvpi6hn.png)

Feito isso, mude para a branch criada no seu local de trabalho, utilizando os seguintes comandos:

```sh
$ git fetch
$ git checkout my_new_branch
```

Como vimos na figura da seção anterior, o `git fetch` irá pegar as modificações do repositório remoto e trazê-las para o repositório local. Isso faz com que o Git local possa identificar que uma nova branch chamada `my_new_branch` foi criada. Com o comando `checkout`, você irá passar a trabalhar nela.

A partir daqui, todas as suas modificações irão ser contempladas e realizadas na sua própria *branch*, sem afetar o código principal. Uma vez que você estiver satisfeito com as suas modificações, você poderá abrir uma *Pull Request*.


### Pull Requests

Se você estiver trabalhando no seu código em uma *branch* específica, a versão principal ficará desatualizada em relação às suas modificações, certo? Por isso, quando você julgar que essas modificações podem fazer parte do código principal, abra uma Pull Request (PR). Pra fazer isso pelo Github, basta você abrir a aba de PR's, clicar em *New Pull Request* e seguir as instruções.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/a5pz0c2nhxljs7v03k06.png)

Vale ressaltar aqui que é **muito importante** que alguém revise suas modificações. Para isso, indique alguém do seu time para ser um "Reviewer" do lado direito da janela principal da PR. Isso faz com que a pessoa veja com clareza as modificações realizadas no seu código, escreva mensagens específicas, aprove ou até faça a requisição de modificações.

Uma vez aprovada a PR, o código principal irá contemplar as suas alterações e você contribuiu para o projeto de uma forma controlada e responsável! 

Tendo em vista que outras pessoas podem ter feito PRs e modificações na *branch* principal, é importante periodicamente rodar o comando `git fetch`. Existe uma opção no VS Code que ele faz isso pra você! 

Se você desejar que as alterações do código feitas venham diretamente para o seu local de trabalho, você também pode utilizar o comando:

```sh
$ git pull
```

Finalizando assim a lista de comandos que eu tinha prometido anteriormente. 

### Motivos para pensarmos em Gitflow

Esse tópico pode até ser considerado um pouco mais avançado, mas a filosofia dele é extremamente importante e eu estou colocando nessa postagem porque eu queria que alguém tivesse me dito isso quando eu estava começando.

Se você já trabalhou com desenvolvimento ou pelo menos foi em algum *meetup*, muito provavelmente você já ouviu a seguinte frase, entoada a plenos pulmões:

*"NUNCA DÊ COMMIT NA MASTER"*

> Mas... por que?

Primeiro que, se você fizer um *commit* no código principal que esteja com algum pequeno *bug*, outras pessoas vão deixar de ter um código que funciona para trabalhar, e isso por si só já pode ser um baita problema. 

Mas vamos pensar mais além, se temos uma aplicação em produção, como um modelo de Análise de Crédito, por exemplo, ele provavelmente vai estar sendo consumido por uma *pipeline* de Integração e *Deploy* contínuos (CI/CD). Isso significa que a aplicação se baseia na *branch* principal para funcionar. Se você der um *commit* diretamente nela, a aplicação vai ser automaticamente atualizada.

Se seu código possui erros, no melhor dos cenários ela para de funcionar. No pior dos cenários, ela irá entregar análises de crédito erradas e até trazer um grande prejuízo pra empresa. Chato, né? Então por isso que é muito importante sempre pensar em trabalhar em *branches* e realizar PR's. Essa é a mensagem.

O termo "Gitflow" é utilizado baseando-se numa metodologia que padroniza a nomenclatura de *branches* e também parte do princípio que o ciclo de vida de uma branch é bem curto - no máximo 3 dias. Isso faz com que o código seja constantemente revisado, que as modificações nele sejam incrementais e que exista uma política de governança bem estabelecida para o trabalho. Se quiser ler mais sobre, veja [essa postagem](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) em inglês da Atlassian.

### Não versione dados com Git

"Bom, se é importante eu salvar meu trabalho e as versões dele, então fica mais fácil já colocar junto também os dados em CSV que eu tô utilizando, certo?"

E aqui vai um grande **NÃO**.

O Git foi feito para controlar inúmeras versões dos códigos escritos justamente porque são arquivos extremamente leves e fáceis de serem controlados. Se você trabalha com dados locais, como arquivos em CSV ou XLSX, crie um arquivo no seu repositório chamado `.gitignore`. Com ele, você vai poder dizer o que o Git não deve olhar quando verificar alterações. Um template que eu uso pode ser escrito assim:

```text
# Python secondary files
__pycache__/
*.py[cod]
*$py.class
.ipynb_checkpoints/

# VS Code config file
.vscode/

# Datasets
*.csv
*.xlsx

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/


# Other files
.idea/
.idea/*
```

Existem ferramentas específicas para versionamento de dados, como o [DVC](https://dvc.org/), mas que fogem do escopo desse artigo.

# Resumão

Nesse meu primeiro artigo, quis trazer um "curso relâmpago" de Git, com algumas especificidades de Data Science pra te ajudar a trilhar essa jornada e estabelecer conhecimentos fundamentais do Desenvolvimento de Software para o seu dia-a-dia.

Sei que se você nunca mexeu com Git essa postagem pode ter sido cheia de jargões ou conceitos que ainda estão um pouco obscuros pra você. Ao mesmo tempo em que é apaixonante, também pode ser exaustivo trabalhar com tecnologia. Não se desespere! Pesquise mais, leia mais e exercite sua curiosidade, que eu garanto que isso tudo vai se esclarecer aos poucos pra você. 

Se mesmo assim tem algum conceito que eu falei aqui e que ainda não tá claro, me manda uma mensagem, comenta aqui em baixo e me ajude a tornar essa postagem ainda mais acessível. 

Um abraço e boa caminhada! 🚀