Git (3/3): repositórios remotos, stash e tags

Git (3/3): repositórios remotos, stash e tags

Nas partes anteriores vimos o controle de versões local e o trabalho com ramos. Neste último capítulo damos o salto para os **repositórios remotos**, criamos **aliases** para ir mais rápido, guardamos alterações sem comprometê-las com o **stash** e marcamos versões com **tags**. 🎸 💾 #GITandRoll

Aviso: Este post foi traduzido para o português usando um modelo de tradução automática. Por favor, me avise se encontrar algum erro.

📚 **Esta entrada faz parte da série _Guia de Git_**, dividida em três capítulos que são lidos em ordem:

> * Parte 1: Controle de versões local

* Parte 2: Ramos

* 👉 **Parte 3: Repositórios remotos, stash e tags**

Trabalhando com repositórios remotoslink image 47

Quando desenvolvemos software, normalmente não o fazemos sozinhos; costumamos trabalhar em equipe, por isso não faz sentido ter um repositório local de git, mas sim ter um repositório remoto com o qual todos trabalhemos e compartilhemos os avanços

Nota: O objetivo deste post é explicar git. Para a conexão com repositórios remotos, vou explicá-lo com GitHub porque é o serviço de hospedagem de repositórios git mais usado, mas não vou entrar em profundidade no GitHub

Clonar um repositório remoto (git clone <repositorio>)link image 48

Se começarmos a trabalhar em um repositório que já foi criado, a primeira coisa que temos de fazer é cloná-lo; para isso, o que temos de fazer é git clone <repositorio>, onde <repositorio> pode ser uma URL ou um endereço SSH. Como agora mesmo todo o tema dos grandes modelos de linguagem e ChatGPT está muito na moda, vamos clonar um repositório open source criado pela comunidade, Open-Assistant, para isso faremos git clone https://github.com/LAION-AI/Open-Assistant

	
< > Input
Python
!git clone https://github.com/LAION-AI/Open-Assistant.git
Copied
>_ Output
			
Clonando en 'Open-Assistant'...
remote: Enumerating objects: 29769, done.
remote: Counting objects: 100% (673/673), done.
remote: Compressing objects: 100% (310/310), done.
remote: Total 29769 (delta 398), reused 577 (delta 354), pack-reused 29096
Recibiendo objetos: 100% (29769/29769), 33.61 MiB | 29.29 MiB/s, listo.
Resolviendo deltas: 100% (19967/19967), listo.

Isso nos cria a pasta Open-Assistant com todo o código do repositório; podemos entrar nela e ver todo o código

	
< > Input
Python
!cd Open-Assistant && ls
Copied
>_ Output
			
ansible deploy model safety
assets discord-bots notebooks scripts
backend docker oasst-data setup.cfg
CODEOWNERS docker-compose.yaml oasst-shared text-frontend
CONTRIBUTING.md docs pyproject.toml website
copilot inference README.md
data LICENSE redis.conf

Eliminou a pasta

	
< > Input
Python
!rm -r Open-Assistant
Copied

Vincular um repositório local a um remotolink image 49

Se acontecer ao contrário, se primeiro começarmos a desenvolver localmente e depois quisermos sincronizar com um repositório remoto, temos de fazer o seguinte

  • Primeiro, crie um repositório remoto vazio; no meu caso, criei o repositório notebook_git no GitHub, que depois apagarei
  • Obter a URL do repositório ou o endereço SSH
  • Sincronizá-los por meio de git remote add origin <URL>

O repositório vazio que criei no GitHub se vê assim

!notebook git repo

No meu caso, vou usar o endereço SSH que é git@github.com:maximofn/notebook_git.git

	
< > Input
Python
!cd notebook_git && git remote add origin git@github.com:maximofn/notebook_git.git
Copied

Já estão vinculados, mas para garantir podemos executar git remote -v

	
< > Input
Python
!cd notebook_git && git remote -v
Copied
>_ Output
			
origin git@github.com:maximofn/notebook_git.git (fetch)
origin git@github.com:maximofn/notebook_git.git (push)

Enviar as alterações de um repositório local para um repositório remoto (git push)link image 50

Como dissemos, eles estão vinculados, mas se eu for ao meu repositório no GitHub, ele continua aparecendo assim

notebook git repo

O repositório local e o remoto estão vinculados, mas agora é preciso enviar todas as alterações do repositório local para o remoto; para isso, deve-se usar git push origin <rama local>:<rama remota>, ou seja, como nossa rama principal se chama main e a rama principal no GitHub se chama main, seria necessário fazer git push origin main:main.

Se você se lembra, o git por padrão chamava a branch principal de master, mas o GitHub chama por padrão a branch principal de main, então, se cada pessoa chama, no seu repositório local, suas branches de uma maneira, é necessário especificar qual branch local grava em qual branch remota

Pode-se configurar a conexão padrão entre ramos no git; para isso, é preciso fazer git push --set-upstream origin main. Isso estabelece uma relação entre a rama local main e a rama remota main. Uma vez feita essa relação, já só é necessário fazer git push para enviar as alterações feitas localmente para o servidor remoto.

De modo que estabelecemos a conexão entre ramos

	
< > Input
Python
!cd notebook_git && git push --set-upstream origin main
Copied
>_ Output
			
Enumerando objetos: 51, listo.
Contando objetos: 100% (51/51), listo.
Compresión delta usando hasta 12 hilos
Comprimiendo objetos: 100% (38/38), listo.
Escribiendo objetos: 100% (51/51), 4.21 KiB | 2.11 MiB/s, listo.
Total 51 (delta 18), reusado 0 (delta 0)
remote: Resolving deltas: 100% (18/18), done.
To github.com:maximofn/notebook_git.git
* [new branch] main -&gt; main
Rama 'main' configurada para hacer seguimiento a la rama remota 'main' de 'origin'.

Agora já podemos fazer apenas git push para enviar as alterações locais para o repositório remoto

	
< > Input
Python
!cd notebook_git && git push
Copied
>_ Output
			
Everything up-to-date

Se agora voltarmos ao nosso repositório do GitHub, ele fica assim

push do repositório git do notebook

Se fizermos um ls no nosso repositório local, poderemos ver que os arquivos que temos no repositório remoto também estão no repositório local, ou seja, sincronizamos o repositório local e o remoto

	
< > Input
Python
!cd notebook_git && ls -a
Copied
>_ Output
			
. .. api_keys.py archivo1.py archivo2.py archivo8.py .git .gitignore

Os únicos que não estão no repositório remoto são api_keys.py, que é o que adicionámos ao ficheiro .gitignore, ou seja, o que dissemos ao git para não seguir. E .git, que é onde está a configuração do nosso repositório local e que não tem de ser enviado para o repositório remoto, porque cada pessoa terá a sua própria configuração do git e, portanto, não tem de ser sincronizada

Baixar as alterações de um repositório remoto para um repositório local (git pull)link image 51

Agora vamos fazer ao contrário, vamos baixar as novas alterações que tenham sido feitas no repositório remoto. Se observarmos como está o repositório remoto, poderemos ver que há um botão que diz Add a README, então clicamos nele para adicioná-lo

notebook git repo push

Ao clicar, um editor será aberto; deixamos o que o GitHub colocou e salvamos as alterações clicando no botão Commit changes...

noteboot git repo readme

Vai aparecer uma janela na qual nos pedirá uma mensagem de commit; deixamos a que vem por padrão e clicamos em Commit changes

notebook git repo commit message

Ao fazer isso, o repositório ficará assim

!pull do repositório git do notebook

Foi criado um novo arquivo chamado README.md, mas se executarmos ls no repositório local não o encontraremos

	
< > Input
Python
!cd notebook_git && ls | grep README
Copied

Como temos que trazer as alterações do repositório remoto para o local, para isso é preciso fazer git pull origin <rama remota> para indicar ao git sobre qual ramo remoto vamos trazer os dados, mas, assim como antes, podemos estabelecer uma relação entre o ramo remoto e o ramo local da seguinte forma git branch --set-upstream-to=origin/<rama local> <rama remota>, mas como nosso ramo local se chama main e o ramo remoto do GitHub também se chama main, teríamos que mudar o anterior para git branch --set-upstream-to=origin/main main.

Uma vez feito isso, para baixar as novas alterações do repositório remoto para o local, só seria necessário fazer git pull

Vamos estabelecer a relação entre branches com git branch --set-upstream-to=origin/main main

	
< > Input
Python
!cd notebook_git && git branch --set-upstream-to=origin/main main
Copied
>_ Output
			
Rama 'main' configurada para hacer seguimiento a la rama remota 'main' de 'origin'.

Agora podemos trazer as alterações do repositório remoto para o repositório local com git pull

	
< > Input
Python
!cd notebook_git && git pull
Copied
>_ Output
			
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Desempaquetando objetos: 100% (3/3), 646 bytes | 646.00 KiB/s, listo.
Desde github.com:maximofn/notebook_git
679bb49..527e07a main -&gt; origin/main
Actualizando 679bb49..527e07a
Fast-forward
README.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 README.md

Como vemos, diz que foi adicionado README.md, verificamos isso fazendo ls

	
< > Input
Python
!cd notebook_git && ls | grep README
Copied
>_ Output
			
README.md

Temos o arquivo localmente

Sincronizar os branches remotos e locaislink image 52

Como vimos, tivemos que sincronizar os branches remotos e locais para poder enviar e baixar os dados. No entanto, se primeiro criarmos o repositório no GitHub e depois o clonarmos, já não é necessária essa sincronização.

Aliaslink image 53

Sempre que quisemos fazer um log, usamos este comando git log --graph --oneline --decorate, no entanto, lembrar-se deste comando é bastante complicado; na verdade, eu não me lembro dele. Cada vez que quis usá-lo, tive que procurá-lo porque não o lembrava, por isso seria ótimo ter uma maneira de o abreviar.

Para isso, o git oferece os alias, de modo que você pode criar aliases dos comandos que quiser; para isso, você tem que executar git config --global alias.<nombre del alias> "comando"

Portanto, vamos chamar git tree ao comando git log --graph --oneline --decorate, já que nos permite ver o histórico, com a bifurcação e fusão de branches como se fosse o crescimento de uma árvore, por isso fazemos git config --global alias.tree "log --graph --oneline --decorate"

**Importante**: Não é necessário colocar a palavra git dentro do comando

	
< > Input
Python
!git config --global alias.tree "log --graph --oneline --decorate"
Copied

Se agora formos ao nosso repositório e executarmos git tree, veremos o histórico como fazíamos antes

	
< > Input
Python
!cd notebook_git && git tree
Copied
>_ Output
			
* 527e07a (HEAD -&gt; main, origin/main) Create README.md
* 679bb49 archivo1.py con el merge resuelto
|\
| * 32851c3 archivo1.py en rama rama_con_conflicto
* | 53f909b archivo1.py en rama main
|/
* 52acb97 Merge squash de los commits de la rama branch_squash
* 274529c Merge branch 'branch_no_fast_forward' into main
|\
| * 8df3429 (branch_no_fast_forward) file2
| * e4e23c9 file1
* | 8bdf4d8 file3
|/
* 94149fc (branch_fast_forward) Eliminado hola.py
* 4484e70 Eliminado archivo4.py
* 564ccfb (new_branch2) Commit con el archivo 8
* 5168f78 Eliminado archivo7.py
* 4bb9d75 (new_branch) Commit con el archivo 7
* ea615a9 Eliminado archivo5.py
* e3153a5 Commit con los archivos 4 y 5
* 0b09cfa Añadido .gitignore
* 04ebd1f Commit con los archivos 1 y 2
* c4930d7 Tercer commit, hola.py
* 6e99e73 Segundo commit, hola.py
* 1c95e4f Primer commit, hola.py

Como vemos, foi criado o nosso alias

Aliases de comandos existentes do gitlink image 54

Podem ser criados aliases de comandos que já existem no git, de fato, é uma prática que muita gente usa, sobretudo para abreviar, por isso vamos fazer um. Vamos fazer um alias do comando git status e vamos renomeá-lo como git st da seguinte forma git config --global alias.st "status"

	
< > Input
Python
!git config --global alias.st "status"
Copied

Vamos testar agora

	
< > Input
Python
!cd notebook_git && git st
Copied
>_ Output
			
En la rama main
Tu rama está actualizada con 'origin/main'.
nada para hacer commit, el árbol de trabajo está limpio

Já temos o comando git status simplificado para git st

Aliases de comandos que não são do gitlink image 55

Podemos criar aliases de comandos que não sejam do git; por exemplo, porque achamos que o git precisa desse novo comando, faz-se da mesma forma, com a exceção de que o comando tem de ir precedido de !, ou seja, seria git config --global alias.<nombre del alias> "!comando"

Quando vimos os conflitos, vimos que o git nos dizia onde estavam, mas para resolvê-los temos de editar o código nós mesmos, por isso podemos criar um alias do git de forma que possamos abrir um ficheiro com o editor de texto que quisermos, no meu caso vou criar um alias que me abrirá os ficheiros com vscode, para isso tenho de fazer git config --global alias.code "!code"

	
< > Input
Python
!git config --global alias.code "!code"
Copied

Vamos testá-lo

	
< > Input
Python
!cd notebook_git && git code README.md
Copied

Depois de fazer isso, foi aberto README.md no VSCode

Lista com todos os aliaslink image 56

No caso de não nos lembrarmos dos aliases que criámos, podemos ver a configuração global do git, mas como isso pode ser um pouco avassalador porque nos dá muita informação, podemos filtrar para que nos mostre apenas os aliases que criámos; para isso usamos git config --get-regexp ^alias\.

	
< > Input
Python
!git config --get-regexp ^alias.
Copied
>_ Output
			
alias.tree log --graph --oneline --decorate
alias.st status
alias.code !code

Obtemos os aliases que criamos

Mas ainda melhor, podemos criar um alias para obter os aliases, para isso fazemos git config --global alias.alias "config --get-regexp ^alias\."

	
< > Input
Python
!git config --global alias.alias "config --get-regexp ^alias."
Copied

Se agora fazemos git alias

	
< > Input
Python
!git alias
Copied
>_ Output
			
alias.tree log --graph --oneline --decorate
alias.st status
alias.code !code
alias.alias config --get-regexp ^alias.

Obtemos a lista com todos os nossos aliases

Armazenar no stash (git stash)link image 57

Suponhamos que estamos trabalhando em uma branch, temos vários arquivos modificados, não fizemos commit, e por alguma razão temos que passar para outra branch. Por exemplo, estamos em uma branch desenvolvendo uma nova funcionalidade, e temos que deixá-la pela metade porque há um bug crítico na branch main

Uma solução seria fazer um commit para guardar as alterações e voltar mais tarde. Mas talvez tenhamos deixado o código pela metade e não queiramos fazer um commit. Então, para isso, foi inventado o stash, que é como um armazém, onde você deixa o seu código armazenado para depois poder recuperá-lo novamente.

É uma pilha, isso quer dizer que o último que entra é o primeiro a sair

Vamos ver como fazer isso, em primeiro lugar, criamos um novo ramo que vamos chamar new_feature

	
< > Input
Python
!cd notebook_git && git branch new_feature
Copied

Mudamos para ela

	
< > Input
Python
!cd notebook_git && git switch new_feature
Copied
>_ Output
			
Cambiado a rama 'new_feature'

Vamos modificar arquivo2.py e arquivo8.py

	
< > Input
Python
!cd notebook_git && echo "print('new_feature')" &gt;&gt; archivo2.py && echo "print('new_feature')" &gt;&gt; archivo8.py
Copied

Fazemos um git status para verificar se foram modificados

	
< > Input
Python
!cd notebook_git && git status
Copied
>_ Output
			
En la rama new_feature
Cambios no rastreados para el commit:
(usa "git add &lt;archivo&gt;..." para actualizar lo que será confirmado)
(usa "git restore &lt;archivo&gt;..." para descartar los cambios en el directorio de trabajo)
modificados: archivo2.py
modificados: archivo8.py
sin cambios agregados al commit (usa "git add" y/o "git commit -a")

Vamos a colocar archivo8.py na área de staged

	
< > Input
Python
!cd notebook_git && git add archivo8.py
Copied

Vamos fazer novamente um git status

	
< > Input
Python
!cd notebook_git && git status
Copied
>_ Output
			
En la rama new_feature
Cambios a ser confirmados:
(usa "git restore --staged &lt;archivo&gt;..." para sacar del área de stage)
modificados: archivo8.py
Cambios no rastreados para el commit:
(usa "git add &lt;archivo&gt;..." para actualizar lo que será confirmado)
(usa "git restore &lt;archivo&gt;..." para descartar los cambios en el directorio de trabajo)
modificados: archivo2.py

Como vemos, temos dois arquivos modificados, dos quais um deles também está na área de staged. Se agora tivéssemos que mudar de branch, para não perder as alterações poderíamos fazer um commit, ou guardá-las no armazenamento stash, então vamos fazer isso último por meio de git stash

	
< > Input
Python
!cd notebook_git && git stash
Copied
>_ Output
			
Directorio de trabajo y estado de índice WIP on new_feature: 527e07a Create README.md guardados

Se agora voltarmos a fazer git status, vejamos o que acontece

	
< > Input
Python
!cd notebook_git && git status
Copied
>_ Output
			
En la rama new_feature
nada para hacer commit, el árbol de trabajo está limpio

Os arquivos modificados já não aparecem, é como se tivéssemos feito um commit

**Importante**: Os arquivos novos criados, que nunca foram rastreados pelo Git, não irão para o repositório, por isso com os arquivos novos é necessário, pelo menos, fazer primeiro um git add

Se eu agora criar um arquivo novo e tentar enviá-lo para o armazenamento, ele me dará um erro

	
< > Input
Python
!cd notebook_git && touch archivo9.py
Copied
	
< > Input
Python
!cd notebook_git && git status
Copied
>_ Output
			
En la rama new_feature
Archivos sin seguimiento:
(usa "git add &lt;archivo&gt;..." para incluirlo a lo que se será confirmado)
archivo9.py
no hay nada agregado al commit pero hay archivos sin seguimiento presentes (usa "git add" para hacerles seguimiento)
	
< > Input
Python
!cd notebook_git && git stash
Copied
>_ Output
			
No hay cambios locales para guardar
	
< > Input
Python
!cd notebook_git && git status
Copied
>_ Output
			
En la rama new_feature
Archivos sin seguimiento:
(usa "git add &lt;archivo&gt;..." para incluirlo a lo que se será confirmado)
archivo9.py
no hay nada agregado al commit pero hay archivos sin seguimiento presentes (usa "git add" para hacerles seguimiento)

Como vemos archivo9.py não foi guardado no repositório, portanto deveria ter sido adicionado com git add.

	
< > Input
Python
!cd notebook_git && rm archivo9.py
Copied

Tudo para o stash (git stash -u -a)link image 58

Como vimos, apenas são enviados para o armazenamento os arquivos aos quais o git está rastreando, mas se tivermos novos arquivos criados, ou arquivos ignorados, eles não serão enviados, então para solucionar isso podemos usar as flags -u ou --include-untracked para que enviem os novos arquivos aos quais o git ainda não fez rastreamento, e a flag -a ou --all para incluir tudo, inclusive os arquivos ignorados

Lista de armazéns (git stash list)link image 59

Como comentamos, o armazenamento atua como uma pilha, portanto, se usarmos esse armazenamento muitas vezes, na verdade vamos ter uma lista de armazenamentos, e para ver os que temos armazenados podemos usar git stash list

	
< > Input
Python
!cd notebook_git && git stash list
Copied
>_ Output
			
stash@{0}: WIP on new_feature: 527e07a Create README.md

Como vemos, só temos uma, que nos indica o ramo (on new_feature), o último commit (Create README.md) e um identificador (527e07a)

Armazenar com descrição (git stash push -m <descrição>))link image 60

Como vimos, a lista nos devolve o ramo e o último commit, mas essa informação só nos serve para saber de onde começámos a modificar antes de guardar no histórico. Além disso, devolve-nos um identificador que não nos diz muito, por isso podemos adicionar uma primeira descrição ao stash com git stash push -m <descripción>

Primeiro fazemos um git status para ver o que temos sem commitar

	
< > Input
Python
!cd notebook_git && git status
Copied
>_ Output
			
En la rama new_feature
Archivos sin seguimiento:
(usa "git add &lt;archivo&gt;..." para incluirlo a lo que se será confirmado)
archivo9.py
no hay nada agregado al commit pero hay archivos sin seguimiento presentes (usa "git add" para hacerles seguimiento)

Temos archivo9.py, mas lembremos que nunca foi seguido pelo git, então para incluí-lo em um stash precisamos usar a flag -u ou a flag -a, de modo que criamos um novo stash com uma descrição com o comando git stash push -u -m <descripción>

	
< > Input
Python
!cd notebook_git && git stash push -u -m "archivo9.py"
Copied
>_ Output
			
Directorio de trabajo y estado de índice On new_feature: archivo9.py guardados

Tiramos a lista do stash

	
< > Input
Python
!cd notebook_git && git stash list
Copied
>_ Output
			
stash@{0}: On new_feature: archivo9.py
stash@{1}: WIP on new_feature: 527e07a Create README.md

Já aparece o novo de maneira muito mais clara

Recuperar o último stash (git stash pop)link image 61

Como dissemos, o stash é uma pilha com armazenamentos, então, na hora de recuperá-los, faremos isso da mesma forma que uma pilha, recuperando sempre o último.

git stash push pop

Para recuperar o último stash, temos que fazer git stash pop

Primeiro fazemos um git status para ver se não temos nenhuma alteração pendente

	
< > Input
Python
!cd notebook_git && git status
Copied
>_ Output
			
En la rama new_feature
nada para hacer commit, el árbol de trabajo está limpio

Agora recuperamos o último stash

	
< > Input
Python
!cd notebook_git && git stash pop
Copied
>_ Output
			
En la rama new_feature
Cambios a ser confirmados:
(usa "git restore --staged &lt;archivo&gt;..." para sacar del área de stage)
nuevos archivos: archivo9.py
Descartado refs/stash@{0} (0246b0e922f654e7fc68cfeaf26e24fc511feb37)

Se voltarmos a executar git status, veremos que voltamos a ter arquivo9.py pendente de fazer um commit

	
< > Input
Python
!cd notebook_git && git status
Copied
>_ Output
			
En la rama new_feature
Cambios a ser confirmados:
(usa "git restore --staged &lt;archivo&gt;..." para sacar del área de stage)
nuevos archivos: archivo9.py

E se verificarmos a lista de stash, veremos que agora só temos um.

	
< > Input
Python
!cd notebook_git && git stash list
Copied
>_ Output
			
stash@{0}: WIP on new_feature: 527e07a Create README.md

Eliminar um stash (git stash drop <posição>)link image 62

Se queremos eliminar um stash, temos que fazer git stash drop <posição>, onde <posição> é a posição que o stash ocupa na lista.

Obtemos a lista dos stashs

	
< > Input
Python
!cd notebook_git && git stash list
Copied
>_ Output
			
stash@{0}: WIP on new_feature: 527e07a Create README.md

No nosso caso, temos apenas um e na posição 0 (stash@{0}), então para eliminá-lo teríamos que fazer git stash drop 0; no entanto, não vou fazer isso porque vou eliminá-lo agora depois com outro comando

Eliminar todos os stashes (git stash clear)link image 63

Se queremos esvaziar a lista inteira de stash, temos que fazer git stash clear

	
< > Input
Python
!cd notebook_git && git stash clear
Copied

Se agora pedimos a lista de stash

	
< > Input
Python
!cd notebook_git && git stash list
Copied

Não obtemos nada porque eliminamos tudo

Vamos deixar tudo como estava, fazemos um git status para lembrar as alterações que tínhamos pendentes

	
< > Input
Python
!cd notebook_git && git status
Copied
>_ Output
			
En la rama new_feature
Cambios a ser confirmados:
(usa "git restore --staged &lt;archivo&gt;..." para sacar del área de stage)
nuevos archivos: archivo9.py

Vemos que estamos na rama new_feature e que temos archivo9.py pendente de fazer um commit. Como o criamos para o exemplo, o eliminamos e voltamos para a rama principal

	
< > Input
Python
!cd notebook_git && git reset archivo9.py
Copied
	
< > Input
Python
!cd notebook_git && rm archivo9.py
Copied
	
< > Input
Python
!cd notebook_git && git switch main
Copied
>_ Output
			
Cambiado a rama 'main'
Tu rama está actualizada con 'origin/main'.

Tagslink image 64

Quando estamos desenvolvendo código, chegam momentos em que geramos versões, por exemplo v1.1, v1.2, etc. Para ter isso mais controlado, o Git nos fornece as tags.

Criar uma nova tag (git tag -a <nome_da_tag> -m "<mensagem>")link image 65

Para criar uma tag temos que fazer git tag -a <nombre_de_etiqueta> -m "<mensaje>"

Por exemplo, vamos criar uma tag na versão atual do repositório, para isso farei git tag -a v_tag -m "Tag con el repositorio en la parte final, en la que explicamos los tags"

	
< > Input
Python
!cd notebook_git && git tag -a v_tag -m "Tag con el repositorio en la parte final, en la que explicamos los tags"
Copied

Lista de tags (git tag)link image 66

Para ver as tags que criamos, podemos fazer git tag

	
< > Input
Python
!cd notebook_git && git tag
Copied
>_ Output
			
v_tag

Criar uma tag de um commit antigo (git tag -a <nome_da_etiqueta> -m "<mensagem>" <hash>)link image 67

Vamos fazer um git tree para ver o histórico

	
< > Input
Python
!cd notebook_git && git tree
Copied
>_ Output
			
* 527e07a (HEAD -&gt; main, tag: v_tag, origin/main, new_feature) Create README.md
* 679bb49 archivo1.py con el merge resuelto
|\
| * 32851c3 archivo1.py en rama rama_con_conflicto
* | 53f909b archivo1.py en rama main
|/
* 52acb97 Merge squash de los commits de la rama branch_squash
* 274529c Merge branch 'branch_no_fast_forward' into main
|\
| * 8df3429 (branch_no_fast_forward) file2
| * e4e23c9 file1
* | 8bdf4d8 file3
|/
* 94149fc (branch_fast_forward) Eliminado hola.py
* 4484e70 Eliminado archivo4.py
* 564ccfb (new_branch2) Commit con el archivo 8
* 5168f78 Eliminado archivo7.py
* 4bb9d75 (new_branch) Commit con el archivo 7
* ea615a9 Eliminado archivo5.py
* e3153a5 Commit con los archivos 4 y 5
* 0b09cfa Añadido .gitignore
* 04ebd1f Commit con los archivos 1 y 2
* c4930d7 Tercer commit, hola.py
* 6e99e73 Segundo commit, hola.py
* 1c95e4f Primer commit, hola.py

Embora isso não esteja indicado na descrição, quando fizemos o commit 4bb9d75 foi quando terminámos a parte de controlo de versões de forma local, pelo que também seria bom ter uma tag desse momento. Para isso, o que temos de fazer é criar uma tag adicionando o hash desse momento

	
< > Input
Python
!cd notebook_git && git tag -a v_local -m "Tag con el repositorio en la parte de control de versiones de manera local" 4bb9d75
Copied

Se agora fizermos uma lista das tags, aparece a nova

	
< > Input
Python
!cd notebook_git && git tag
Copied
>_ Output
			
v_local
v_tag

E se vemos o histórico de commits

	
< > Input
Python
!cd notebook_git && git tree
Copied
>_ Output
			
* 527e07a (HEAD -&gt; main, tag: v_tag, origin/main, new_feature) Create README.md
* 679bb49 archivo1.py con el merge resuelto
|\
| * 32851c3 archivo1.py en rama rama_con_conflicto
* | 53f909b archivo1.py en rama main
|/
* 52acb97 Merge squash de los commits de la rama branch_squash
* 274529c Merge branch 'branch_no_fast_forward' into main
|\
| * 8df3429 (branch_no_fast_forward) file2
| * e4e23c9 file1
* | 8bdf4d8 file3
|/
* 94149fc (branch_fast_forward) Eliminado hola.py
* 4484e70 Eliminado archivo4.py
* 564ccfb (new_branch2) Commit con el archivo 8
* 5168f78 Eliminado archivo7.py
* 4bb9d75 (tag: v_local, new_branch) Commit con el archivo 7
* ea615a9 Eliminado archivo5.py
* e3153a5 Commit con los archivos 4 y 5
* 0b09cfa Añadido .gitignore
* 04ebd1f Commit con los archivos 1 y 2
* c4930d7 Tercer commit, hola.py
* 6e99e73 Segundo commit, hola.py
* 1c95e4f Primer commit, hola.py

No ponto do histórico em que criámos a tag, agora aparece a tag que criámos * 4bb9d75 (tag: v_local, new_branch) Commit com o arquivo 7

Mudar entre tags (git reset --hard <tag> ou git reset --soft <tag>)link image 68

Assim como podemos nos mover entre diferentes commits do histórico, também podemos nos mover entre tags. Isso tem a vantagem de que podemos ir para outro momento do histórico sem precisar saber o hash; sabendo o nome da tag que definimos naquele momento, podemos nos mover simplesmente fazendo git reset --hard <tag> ou git reset --soft <tag>

Primeiro vamos fazer um ls para ver os arquivos que temos

	
< > Input
Python
!cd notebook_git && ls
Copied
>_ Output
			
api_keys.py archivo1.py archivo2.py archivo8.py README.md

Fazemos também um git tree para ver em que momento do histórico estamos

	
< > Input
Python
!cd notebook_git && git tree
Copied
>_ Output
			
* 527e07a (HEAD -&gt; main, tag: v_tag, origin/main, new_feature) Create README.md
* 679bb49 archivo1.py con el merge resuelto
|\
| * 32851c3 archivo1.py en rama rama_con_conflicto
* | 53f909b archivo1.py en rama main
|/
* 52acb97 Merge squash de los commits de la rama branch_squash
* 274529c Merge branch 'branch_no_fast_forward' into main
|\
| * 8df3429 (branch_no_fast_forward) file2
| * e4e23c9 file1
* | 8bdf4d8 file3
|/
* 94149fc (branch_fast_forward) Eliminado hola.py
* 4484e70 Eliminado archivo4.py
* 564ccfb (new_branch2) Commit con el archivo 8
* 5168f78 Eliminado archivo7.py
* 4bb9d75 (tag: v_local, new_branch) Commit con el archivo 7
* ea615a9 Eliminado archivo5.py
* e3153a5 Commit con los archivos 4 y 5
* 0b09cfa Añadido .gitignore
* 04ebd1f Commit con los archivos 1 y 2
* c4930d7 Tercer commit, hola.py
* 6e99e73 Segundo commit, hola.py
* 1c95e4f Primer commit, hola.py

Agora passamos ao ponto em que criamos a tag v_local por meio de git reset --hard v_local

	
< > Input
Python
!cd notebook_git && git reset --hard v_local
Copied
>_ Output
			
HEAD está ahora en 4bb9d75 Commit con el archivo 7

Se agora fizermos novamente um ls, vemos que não temos os mesmos arquivos

	
< > Input
Python
!cd notebook_git && ls
Copied
>_ Output
			
api_keys.py archivo1.py archivo2.py archivo4.py archivo7.py hola.py

Se também olharmos o histórico, vemos que mudámos de momento do histórico

	
< > Input
Python
!cd notebook_git && git tree
Copied
>_ Output
			
* 4bb9d75 (HEAD -&gt; main, tag: v_local, new_branch) Commit con el archivo 7
* ea615a9 Eliminado archivo5.py
* e3153a5 Commit con los archivos 4 y 5
* 0b09cfa Añadido .gitignore
* 04ebd1f Commit con los archivos 1 y 2
* c4930d7 Tercer commit, hola.py
* 6e99e73 Segundo commit, hola.py
* 1c95e4f Primer commit, hola.py

Para voltar ao último momento do histórico, como também criamos uma tag, bastará fazer git reset --hard v_tag

	
< > Input
Python
!cd notebook_git && git reset --hard v_tag
Copied
>_ Output
			
HEAD está ahora en 527e07a Create README.md

Voltamos a ver o histórico para verificar que retornamos ao último momento do histórico

	
< > Input
Python
!cd notebook_git && git tree
Copied
>_ Output
			
* 527e07a (HEAD -&gt; main, tag: v_tag, origin/main, new_feature) Create README.md
* 679bb49 archivo1.py con el merge resuelto
|\
| * 32851c3 archivo1.py en rama rama_con_conflicto
* | 53f909b archivo1.py en rama main
|/
* 52acb97 Merge squash de los commits de la rama branch_squash
* 274529c Merge branch 'branch_no_fast_forward' into main
|\
| * 8df3429 (branch_no_fast_forward) file2
| * e4e23c9 file1
* | 8bdf4d8 file3
|/
* 94149fc (branch_fast_forward) Eliminado hola.py
* 4484e70 Eliminado archivo4.py
* 564ccfb (new_branch2) Commit con el archivo 8
* 5168f78 Eliminado archivo7.py
* 4bb9d75 (tag: v_local, new_branch) Commit con el archivo 7
* ea615a9 Eliminado archivo5.py
* e3153a5 Commit con los archivos 4 y 5
* 0b09cfa Añadido .gitignore
* 04ebd1f Commit con los archivos 1 y 2
* c4930d7 Tercer commit, hola.py
* 6e99e73 Segundo commit, hola.py
* 1c95e4f Primer commit, hola.py

Continuar lendo

Últimos posts -->

Você viu esses projetos?

Gymnasia

Gymnasia Gymnasia
React Native
Expo
TypeScript
FastAPI
Next.js
OpenAI
Anthropic

Aplicativo móvel de treino pessoal com assistente de IA, biblioteca de exercícios, acompanhamento de rotinas, dieta e medidas corporais

Horeca chatbot

Horeca chatbot Horeca chatbot
Python
LangChain
PostgreSQL
PGVector
React
Kubernetes
Docker
GitHub Actions

Chatbot conversacional para cozinheiros de hotéis e restaurantes. Um cozinheiro, gerente de cozinha ou serviço de quarto de um hotel ou restaurante pode falar com o chatbot para obter informações sobre receitas e menus. Mas também implementa agentes, com os quais pode editar ou criar novas receitas ou menus

Naviground

Naviground Naviground
Ver todos os projetos -->
>_ Disponível para projetos

Tem um projeto com IA?

Vamos conversar.

maximofn@gmail.com

Especialista em Machine Learning e Inteligência Artificial. Desenvolvo soluções com IA generativa, agentes inteligentes e modelos personalizados.

Quer assistir alguma palestra?

Últimas palestras -->

Quer melhorar com essas dicas?

Últimos tips -->

Use isso localmente

Os espaços do Hugging Face nos permitem executar modelos com demos muito simples, mas e se a demo quebrar? Ou se o usuário a deletar? Por isso, criei contêineres docker com alguns espaços interessantes, para poder usá-los localmente, aconteça o que acontecer. Na verdade, se você clicar em qualquer botão de visualização de projeto, ele pode levá-lo a um espaço que não funciona.

Flow edit

Flow edit Flow edit

Edite imagens com este modelo de Flow. Baseado em SD3 ou FLUX, você pode editar qualquer imagem e gerar novas

FLUX.1-RealismLora

FLUX.1-RealismLora FLUX.1-RealismLora
Ver todos os contêineres -->
>_ Disponível para projetos

Tem um projeto com IA?

Vamos conversar.

maximofn@gmail.com

Especialista em Machine Learning e Inteligência Artificial. Desenvolvo soluções com IA generativa, agentes inteligentes e modelos personalizados.

Você quer treinar seu modelo com esses datasets?

short-jokes-dataset

HuggingFace

Dataset com piadas em inglês

Uso: Fine-tuning de modelos de geração de texto humorístico

231K linhas 2 colunas 45 MB
Ver no HuggingFace →

opus100

HuggingFace

Dataset com traduções de inglês para espanhol

Uso: Treinamento de modelos de tradução inglês-espanhol

1M linhas 2 colunas 210 MB
Ver no HuggingFace →

netflix_titles

HuggingFace

Dataset com filmes e séries da Netflix

Uso: Análise de catálogo Netflix e sistemas de recomendação

8.8K linhas 12 colunas 3.5 MB
Ver no HuggingFace →
Ver mais datasets -->