git
Table of Contents
- 1. Git
- 1.1. Git Mental Models
- 1.2. Introductory resources
- 1.3. Cheatsheets
- 1.3.1. https://dev.to/doabledanny/git-cheat-sheet-50-commands-free-pdf-and-poster-4gcn
- 1.3.2. https://about.gitlab.com/images/press/git-cheat-sheet.pdf
- 1.3.3. http://ndpsoftware.com/git-cheatsheet.html#loc=index;
- 1.3.4. https://blog.osteele.com/2008/05/my-git-workflow/
- 1.3.5. https://github.com/abduvik/just-enough-series/tree/master/courses/git
- 1.3.6. Commit Often, Perfect Later, Publish Once—Git Best Practices
- 1.3.7. Version Control System: The One Computer Skill
- 1.4. https://github.com/dictcp/awesome-git
- 1.5. Git is simply too hard |> Changelog
- 1.6. What’s wrong with Git? A conceptual design analysis | the morning paper
- 1.7. lazygit
- 1.8. Tortoise Git
- 1.9. Tricks
- 1.10. Changelog
- 1.11. What if git parsed syntax? structural diff
- 1.12. Pre-commit hooks
- 1.13. Archivos binarios con git
- 1.14. Credenciales en git
- 1.15. Rebase vs never rebase
- 1.16. Git alternatives
- 1.17. Firmar commits / sign commits
- 1.18. Git Workflows
- 1.18.1. GitOps Decisions
- 1.18.2. Versioning
- 1.18.3. Git commit style
- 1.18.4. Things I wish Git had: Commit groups
- 1.18.5. A successful Git branching model (Git Flow)
- 1.18.6. GitFlow considered harmful | End of Line Blog
- 1.18.7. Please stop recommending Git Flow! – George Stocker
- 1.18.8. Trunk based development
- 1.18.9. Monorepo
- 1.18.10. Multiple repo management
- 1.18.11. Merge Window
- 1.19. https://devhints.io/git-log-format
- 1.20. Fake random git man page generator
- 1.21. Misc
- 1.22. Git for Excel
- 1.23. Cambiarme a un setup de git con wip, squash, worktree y zsh, + lazygit project someday_20230330
- 1.24. Git Alternatives
- 1.25. github
- 1.26. Github Alternatives
- 1.27. Tools for Git Analysis
- 1.28. Pitfalls & Gotchas
- 1.29. Git en profundidad
- 1.29.1. git add
- 1.29.2. git commit
- 1.29.3. git log
- 1.29.4. git merge
- 1.29.5. git grep
- 1.29.6. cherry picking y diff apply
- 1.29.7. On undoing, fixing, or removing commits in git
- 1.29.8. Git Fix Um — On undoing, fixing, or removing commits in git
- 1.29.9. Información
- 1.29.10. Configuración
- 1.29.11. remotes
- 1.29.12. Herramientas
- 1.29.13. Creating a Git commit: The Hard Way
1. Git
1.1. Git Mental Models
1.2. Introductory resources
- Official Documentation and manual
- Interactive git tutorial
- Flight rules for Git
- Oh Shit, Git!?!
- https://wizardzines.com/zines/oh-shit-git/
- GIT PURR! Git Commands Explained with Cats! – GirlieMac! Blog
- game about learning git
https://stevelosh.com/blog/2013/04/git-koans/
Triggers “Aha!” moments about git concepts. Example:
"How should I change to a different branch?" asked the programmer. "Use git checkout." "And how should I create a branch?" "Use git checkout." "And how should I update the contents of a single file in my working directory, without involving branches at all?" "Use git checkout."
- firstcontributions/first-contributions: 🚀✨ Help beginners to contribute to open source projects
- https://my-learning.w3schools.com/tutorial/git
- Git+Jupytext+Google Colab Workflow:
- A Visual Git Reference
- Explain Git with D3
1.2.1. Guía rápida
1.2.1.1. Ciclo básico de desarrollo
git clone <url del repositorio> # Descargar el repositorio (sólo una vez, al principio) git pull # Pillar lo que ha cambiado desde la última vez <modificar un archivo> git add <archivo> git add * # añadir todo lo que se ha modificado git commit -m "He cambiado esto y esto otro" git push # Sube los cambios al servidor
git log
sirve para ver los commits pasados. Se puede filtrar por
usuario, no mostrar los merges, filtrar por fecha, grepear, …
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
para que se vea bonito, git lg -p
para ver el diff de cada commit
- Configurar
user.name, user.email, core.editor
- Configurar .gitattributes para los saltos de línea
git ls-files --deleted | xargs git add
añadir sólo archivos borradosgit diff --no-index A B
para diff con estilos de git
1.2.1.2. Deshaciendo cosas
git reset HEAD <archivo>
deshacegit add <archivo>
git reset HEAD
deshace todos losgit add
que hayamos hechogit commit --amend
antes degit push
enmienda el commit que hemos
hechogit checkout -- <archivo>
BORRA los cambios (locales) del archivo
sin commitear y lo reemplaza con la versión que hay en el repositoriogit stash
Descarta los cambios locales, pero los guarda para más
tarde congit stash pop
git reset --hard
Resetea el repositorio local, BORRA y reemplaza
para que el repositorio local se quede igual que el remotogit checkout <hash del commit>
Cambia a un commit anterior para ver
cambios.git revert <hash del commit>
DESHACE y BORRA todos los cambios a
partir del commit indicado.git reset --hard
esencialmente revierte
al último commitgit reset --hard <hash del commit>
resetea todo a ese commit, por si
tienes algunos commits que no quieres subirgit revert --no-commit master~9..master
revierte los últimos 9
commits de master
1.2.1.3. He subido archivos binarios al git y tarda 15min en clonarse
git filter-branch --tree-filter "rm -r -f <path/al/archivo/maligno>" HEAD
- Forzar el push
- Limpar contraseñas y binarios de repos
- How to find/identify large commits in git history? - Stack Overflow
1.2.1.4. reset vs checkout
- Situación inicial
object master object HEAD e138c7e -> 72625a3 72625a3 -> 13b2cbe 13b2cbe -> 75cdf49 master --|> 75cdf49 HEAD --|> master
git reset 13b2cbe
object master object HEAD e138c7e -> 72625a3 72625a3 -> 13b2cbe 13b2cbe -> 75cdf49 master --|> 13b2cbe HEAD --|> master
git checkout 13b2cbe
(Produce detached HEAD)
object master object HEAD e138c7e -> 72625a3 72625a3 -> 13b2cbe 13b2cbe -> 75cdf49 master --|> 75cdf49 HEAD --|> 13b2cbe
DETACHED HEAD se soluciona simplemente con: git checkout <rama>
1.2.1.5. Borrando cosas
git push origin --delete branch
eliminaorigin/branch
(remoto)git push --delete origin mytag
lo elimina en remoto, y
git tag rm mytag
en local
1.2.1.6. Arreglando desastres
git push origin HEAD:<branch>
cuando estamos en detached HEAD y
queremos hacer un commit. Me ha pasado cuando hago
git checkout <commit antiguo>; git merge origin <branch>; git push # FALLA
,
en vez de hacergit revert
porque había muchos commits en medio.
Después habrá que hacergit pull; git checkout <branch>
porque
seguimos trabajando en detached HEAD
1.2.1.7. Evitando desastres
- Antes de hacer un rebase de new_feature contra una rama old_feature,
que partió de una rama estable como master, hay que hacer primero un
rebase de old_feature contra master, por que si divergen las
historias, hay conflictos
- Una alternativa sería mergear de new_feature con old_feature, pero
si la rama está desactualizada, git sabe qué commits tiene que
coger? (Creo que sí)
- Una alternativa sería mergear de new_feature con old_feature, pero
1.2.2. https://git-scm.com/docs/giteveryday → basic commands split by roles
Git users can broadly be grouped into four categories for the purposes of describing here a small set of useful command for everyday Git.
- Individual Developer (Standalone) commands are essential for anybody who makes a commit, even for somebody who works alone.
«Invividual Developer (Standalone) Always open a branch for an Individual Developer because a failing git push (because a git pull is needed) is scary» - If you work with other people, you will need commands listed in the Individual Developer (Participant) section as well.
- People who play the Integrator role need to learn some more commands in addition to the above.
- Repository Administration commands are for system administrators who are responsible for the care and feeding of Git repositories.
1.3. Cheatsheets
1.3.1. https://dev.to/doabledanny/git-cheat-sheet-50-commands-free-pdf-and-poster-4gcn
What it doesn’t have: “switch” and “restore” commands delete remote branchs and tags also
1.3.6. Commit Often, Perfect Later, Publish Once—Git Best Practices
Best Practices, maintenance of a git repo, …
1.3.7. Version Control System: The One Computer Skill
1.5. Git is simply too hard |> Changelog
How do I delete a branch?
and then I have to ask them:
Well, what do you want to do? Do you wanna delete a local branch, and then just get it recreated when you pull again from the same remote? Or delete the remote tracking branch? Or delete the remote branch?
1.6. What’s wrong with Git? A conceptual design analysis | the morning paper
Fred Brooks described conceptual integrity as “the most important consideration in system design” and gave three principles upon which it is based:
- propriety – a product should have only the functions (concepts) essential to its purpose and no more, and
- generality a single function (concept) should be usable in many ways.
The authors add a fourth:
- consistency – requiring for example that actions behave in a similar way irrespective of the arguments they are presented with or the states in which they are invoked.
1.7. lazygit
1.7.1. 15 Lazygit Features In Under 15 Minutes - YouTube
- Move between panels with h,l/←,→ and move inside each panel with j,k/↑,↓
- Files panel>Toggle stage whole file with
SPC
- When the files are staged, commit with
c
,C
if you want a multiline commit g
to reset: soft, mixed and harda
to toggle stage all filesRET
to path stage line by line withSPC
, or with visual line select usingv
and thenSPC
(v
toggles between visual line and normal mode)- Cycle between unstaged and staged lines/hunks with
TAB
d
to delete line in unstaged panel,d
to unstage line in staged panelRET
on a branch to see its commits (git log on the side)p/P
on a branch to pull/PushRET
on a commit to see its changes (diff of each file)- Cherry pick a commit from a branch with
c
in the “Local Branches/Remotes/Tags” panel and paste it ont the “Commits/Reflog” panel withv
s
to stage a file,S
stage more selectivelyd
to reset a file (discard changes)D
to nuke working tree, discard untracked files, and soft/hard reset
1.7.2. sign commits
1.7.4. squash
No puedes cambiar el contenido del commit, con lo que se queda con un wip
1.8. Tortoise Git
TortoiseGit – TortoiseGit – Documentation – TortoiseGit – Windows Shell Interface to Git
https://tortoisegit.org/docs/tortoisegit/
https://tortoisegit.org/about/
1.9. Tricks
- rebase squash
git rebase -i HEAD~<number of commits to maybe squash>
https://thoughtbot.com/blog/git-interactive-rebase-squash-amend-rewriting-history - git pull sin cambiarse a esa rama
git fetch origin master:master
- Mostrar un archivo de otra rama
git show branch:file
https://superuser.com/questions/232373/how-to-tell-git-which-private-key-to-use
In~/.ssh/config
, add:
Host github.com HostName github.com IdentityFile ~/.ssh/id_rsa_github
Más sencillo:
GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_example" git clone example
https://stackoverflow.com/questions/1143796/remove-a-file-from-a-git-repository-without-deleting-it-from-the-local-filesyste/21404811#21404811
Ignore file changed
git update-index --assume-unchanged superimportant-secret-key
1.10. Changelog
A changelog is a kind of summary of commits
1.11. What if git parsed syntax? structural diff
1.12. Pre-commit hooks
1.12.2. Pre-commit que luego hace un commit
Es posible que te empieze a generar commits infinitos si pones git commit en el propio git commit
https://stackoverflow.com/questions/3284292/can-a-git-hook-automatically-add-files-to-the-commit
1.13. Archivos binarios con git
1.13.1. How to manage binary assets with Git | Opensource.com
1.13.2. Git LFS, git-annex
https://git-lfs.github.com/ https://git-annex.branchable.com/ → quizás más interesante que git-lfs
1.13.3. Limpar contraseñas y binarios de repos
https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/removing-sensitive-data-from-a-repository
https://medium.com/@vegeta2102/why-you-should-not-push-binary-files-to-git-and-what-to-do-if-you-do-29f34692cef0
https://rtyley.github.io/bfg-repo-cleaner/ No pilla los caracteres de escape y comillas bien
https://github.com/newren/git-filter-repo/tree/main/Documentation → Esta va mejor con escape y comillas
git grep -l "sensitive_string" $(git rev-list --all)
1.13.3.1. Ejecutarlo
alias bfg='docker run -it -v $PWD:/pwd -v $HOME/.local/share/linuxbrew:/home/linuxbrew --entrypoint bfg linuxbrew/brew' bfg --replace-text /pwd/replace /pwd sudo chown -R julian:julian .git # Ejecutarlo con docker te cambia los permisos de .git bfg --delete-files 'script.cpython-38.pyc' /pwd
1.13.4. Sparse Checkout
git clone --depth 1 --no-checkout --filter=blob:none https://github.com/ryanoasis/nerd-fonts echo 'patched-fonts/FiraCode' >> .git/info/sparse-checkout && git config core.sparseCheckout true && \ git checkout master -- patched-fonts/FiraMono
1.14. Credenciales en git
https://github.com/lu0/syncthing-config/blob/master/pre-commit → alerta cuando comiteas código que no debes
Para pillar todo lo que hay en .env y pasarlo como credencial:
cat .env | awk -F = '{$1=""; print $0}' | sed -Ez 's/\n+/\n/g' | sed 's/^ //' | tr '\n' '|' | copy
#!/bin/bash sensitive="apikey|password|urUniqueID" flags=$(git diff -U0 --no-ext-diff --staged | grep -E -i --count "$sensitive") if [ "$flags" -ne "0" ]; then echo "WARNING! You are attempting to commit sensitive data from:" git diff --no-ext-diff --staged --name-only -i -G "$sensitive" | sed 's/^/\t*/' echo -e "\nPlease review and unstage relevant hunks of those files with" echo -e "\tgit reset --patch" echo -e "\nCommit using the '--no-verify' option to ignore this warning (not recommended)\n\n" echo -e "Sensitive matches found:" git diff --no-ext-diff --staged | grep -E -i "$sensitive" exit 1 fi
1.15. Rebase vs never rebase
- Rebase:
- fearless-git: Rewrite Git History Like There’s No Tomorrow
- Learn to change history with git rebase!
One of Git’s core value-adds is the ability to edit history. Unlike other version control systems that treat the history as a sacred record, in git we can change history to suit our needs. - Branching and the power of rebase | Git from the Bottom Up
- fearless-git: Rewrite Git History Like There’s No Tomorrow
- Not Rebase:
git is an historical archive of how the code was at a given moment of time, so rebasing is destroying that history - You only Git Merge?!? feat Theo : DevHour #1 - YouTube
- Rebasing creates source code states that never existed, since you take some change and reapplying them on top of a different history. For example git bisect doesn’t work with this
- Rebasing creates source code states that never existed, since you take some change and reapplying them on top of a different history. For example git bisect doesn’t work with this
- Should You Squash Merge or Merge Commit? - Wait, so why don’t you like rebasing?
Fundamentally, I dislike rebasing because of it’s possibly destructive nature. Sure, there are also a number of proponents of rebasing - usually spouting pithy advice such as “It’s not destructive, if you use Git right”.
Git is already hard enough to use with a very poor and inconsistent developer experience that leads to too many mistakes. Telling developers to just “use Git right” when rebasing could result in you overwriting a team members work feels somewhat thoughtless
Finally, merge conflicts during a rebase result in some of the worst developer experience imaginable. Each conflict will be represented one commit at a time ad nauseam. This is confusing and an easy way to pick the wrong side of the conflict. Reversing a rebase is difficult. Merge conflicts during a merge are presented all at once
Discussion: https://www.reddit.com/r/programming/comments/whav9l/should_you_squash_merge_or_merge_commit/ - SQLite Doesn’t Use Git
- Fossil: Rebase Considered Harmful
- Rebasing is dangerous
- Rebase provides no new capabilities
- A rebase is just a merge with historical references omitted
- Rebase does not actually provide better feature-branch diffs
- A rebase is just a merge with historical references omitted
- Rebase encourages siloed development
- Rebase causes timestamp confusion
- Rebase misrepresents the project history
- Collapsing check-ins throws away valuable information
- Individual check-ins support mutual understanding
- Bisecting works better on small check-ins
- Multiple check-ins require multiple check-in comments
- Cherry-picks work better with small check-ins
- Back-outs also work better with small check-ins
- Individual check-ins support mutual understanding
- Cherry-pick merges work better than rebase
- Summary and conclusion
Rebasing is an anti-pattern. It is dishonest. It deliberately omits historical information. It causes problems for collaboration. And it has no offsetting benefits.
For these reasons, rebase is intentionally and deliberately omitted from the design of Fossil.
- Rebasing is dangerous
- Fossil: Rebase Considered Harmful
-
- Rebase rewrites history on top of a branch. This provides a linear history, meaning context is lost of where a feature branched off. You may also have to force push changes (since you are rewriting history) if you have already pushed to a remote.
- Merge will create a merge commit that joins two branches together. With the fast-forward-only flag
ff-only
, git will attempt to merge without a merge commit, but this isn’t possible if the branches have diverged (i.e., there has been a commit to the parent branch that’s not on the feature branch). - Squash + Merge acts like merge but creates a single new squashed commit that encompasses all commits in the feature branch.
I use rebase. Rebase retains a linear commit history, which is important for rollbacks. In addition, rebase is the most flexible workflow – larger and more difficult merges can be tough to do with a squash and merge. Interactive rebase has a bit of a steeper learning curve, but with practice, it can work in all scenarios. Squash and merge is OK for smaller changes, but it might be smarter to break large feature branches into multiple logical commits. This is useful for cherry-picking commits to other branches or repositories.
- Rebase rewrites history on top of a branch. This provides a linear history, meaning context is lost of where a feature branched off. You may also have to force push changes (since you are rewriting history) if you have already pushed to a remote.
- Git team workflows: merge or rebase? | Atlassian Git Tutorial
Rebase as team policy is a different thing than rebase as cleanup.
- Rebase as cleanup, even when sharing your feature branch
- You’re developing locally and have not shared your work even if you have pushed it. Rebase is fine
- Your code is ready for review. You create a pull request, others are reviewing your work and are potentially fetching it into their fork for local review. You should not rebase
You should create ’rework’ commits and update your feature branch. This helps with traceability in the pull request, and prevents the accidental history breakage. - Review is done and ready to be integrated into the target branch. Given that other developers won’t be fetch-merging, you can rebase now
- You’re developing locally and have not shared your work even if you have pushed it. Rebase is fine
- Rebase as a team policy
- ↑ Code history remains flat and readable. Clean, clear commit messages are documentation, do not to pollute history
- ↑ Manipulating a single commit is easy (e.g. reverting them).
- ↓ Squashing the feature down to a handful of commits can hide context, unless you keep around the historical branch with the entire development history.
- ↓ Rebasing doesn’t play well with pull requests, because you can’t see what minor changes someone made if they rebased (never rebase during a pull request).
- ↓ Rebasing can be dangerous and is prone to team work breakage
This can be mitigated by doing the rebase/squash on a copy of the feature branch - It’s more work: Using rebase to keep your feature branch updated requires that you resolve similar conflicts again and again.
You can reuse recorded resolutions (rerere) sometimes, butmerges
win here: Just solve the conflicts one time, and you’re set. - you need to force push at some point. If people haven’t set
git push.default
⇒ updates to all branches having the same name, both locally and remotely, and that is dreadful to deal with.
- ↑ Code history remains flat and readable. Clean, clear commit messages are documentation, do not to pollute history
- Rebase as cleanup, even when sharing your feature branch
NOTE: When history is rewritten in a shared branch touched by multiple developers breakage happens.
1.16. Git alternatives
1.16.1. Pijul
- Commutation
In Pijul, independent changes can be applied in any order without changing the result or the version’s identifier. This makes Pijul significantly simpler than workflows usinggit rebase
orhg transplant
. Pijul has a branch-like feature called “channels”, but these are not as important as in other systems. For example, so-called feature branches are often just changes in Pijul. Keeping your history clean is the default. - Merge correctness
Pijul guarantees a number of strong properties on merges. The most important one is that the order between lines is always preserved. This is unlike 3-way merge, which may sometimes shuffle lines around. When the order is unknown (for example in the case of concurrent edits), this is a conflict, which contrasts with systems with “automatic” or “no conflicts” merges. - First-class conflicts
In Pijul, conflicts are not modelled as a “failure to merge”, but rather as the standard case. Specifically, conflicts happen between two changes, and are solved by one change. The resolution change solves the conflict between the same two changes, no matter if other changes have been made concurrently. Once solved, conflicts never come back. - Partial clones
Commutation makes it possible to clone only a small subset of a repository: indeed, one can only apply the changes related to that subset. Working on a partial clone produces changes that can readily be sent to the large repository.
1.17. Firmar commits / sign commits
gpg --list-secret-keys --keyid-format=long # sec algorithm_or_number/61690A4ABCDFE59C gpg --armor --export 61690A4ABCDFE59C | copy git config --global commit.gpgsign git config --global user.signingkey 61690A4ABCDFE59C export GPG_TTY=$(tty) # Put it in your .bashrc/.zshrc
1.18. Git Workflows
1.18.1. GitOps Decisions
1.18.2. Versioning
1.18.2.1. https://semver.org/
1.18.2.2. https://calver.org/
1.18.2.3. https://chronver.org/
1.18.2.4. Designing a version
1.18.3. Git commit style
1.18.3.1. Commit Message Style Guide For Git
1.18.3.3. Conventional Commits, Commitizen, Auto Changelog
- Conventional Commits
- Commitizen -> Generar Changelogs en base a Conventional Commits
https://github.com/KeNaCo/auto-changelog → Auto changelog basado en commits
pip install -U commitizen pip install pre-commit
1.18.3.4. https://www.danclarke.com/git-tense
1.18.3.5. https://whatthecommit.com/ → anti commit style
1.18.3.6. Good references
1.18.4. Things I wish Git had: Commit groups
1.18.4.1. Things I wish Git had: Commit groups
- Create a merge commit with –no-ff
- ↑ extremely versatile and scale well, especially for complicated workflows with multiple maintainers, each responsible for different part of the code
- ↓ probably overkill for small groups ⇒ potential problems
- ↓ Complicated to see concurrent changes to the code, entangled graph
- ↓ complicated to answer questions such as:
- “which features were released over the given time period?”
- “what was the state of main as of a given date?”.
- “which features were released over the given time period?”
- ↓ harder to revert changes (implies reverting multiple commits)
- ↑ extremely versatile and scale well, especially for complicated workflows with multiple maintainers, each responsible for different part of the code
- Squash and merge
- ↑ very legible history (linear)
- ↑ easier to revert a feature (git revert one commit)
- ↓ squashing irrevocably loses context, especially if branch has been deleted
- ↑ very legible history (linear)
- Rebase and merge
- ↑ linear history with multiple commits
- ↓ harder to revert changes: typically you want to operate on a feature level there as in Squash and merge
- git commits have to be meaningful to use this approach
- ↑ linear history with multiple commits
- Rebase, group and merge
You draw a couple of shapes, you group them together, and then you can apply transformations to the entire group at once, operating on it as if it were an atomic thing. But when need arises, you can “ungroup” it and look deeper.
That’s because sometimes there’s a need to have a “high-level” view of things, and sometimes you need to delve deeper. Each of these needs is valid. Each is prompted by different circumstances that we all encounter.
1.18.5. A successful Git branching model (Git Flow)
In the beggining, it was Git Flow. Then it was considered harmful
1.18.6. GitFlow considered harmful | End of Line Blog
1.18.7. Please stop recommending Git Flow! – George Stocker
1.18.8. Trunk based development
1.18.9. Monorepo
1.18.9.1. Tools for monorepo management - packages linking, versioning, publishing : Python
1.18.9.2. Google Research uses one repo
https://github.com/google-research/google-research
- Some people have their own branches
https://github.com/ekinakyurek/google-research/tree/master/incontext
1.18.10. Multiple repo management
Submodules aren’t more straightforward? There is a git submodule foreach command
1.18.10.1. mu-repo
1.18.10.2. Git - git-for-each-repo Documentation
1.18.11. Merge Window
2. How the development process works — The Linux Kernel documentation
At the beginning of each development cycle, the “merge window” is said to be open. The merge window lasts for approximately two weeks.
Over the next six to ten weeks, only patches which fix problems should be submitted to the mainline. On occasion a more significant change will be allowed, but such occasions are rare
(An occasional exception is made for drivers for previously-unsupported hardware; if they touch no in-tree code, they cannot cause regressions and should be safe to add at any time)
1.21. Misc
1.22. Git for Excel
1.23. Cambiarme a un setup de git con wip, squash, worktree y zsh, + lazygit project someday_20230330
La idea es hacer un montón de commits en local y luego juntarlos antes de subirlos
alias gwip='git commit -a -m "work in progress - fixup"'
Things I wish Git had: Commit groups → Un poco relaccionado con todo esto
-—
- Commit en local al principio
- Hacer commits que tengan wip para que los vea en zsh
- Squash de todos ellos antes de subirlos
- Suele pasar que tienes cambios en local (el repo no está limpio) → hacer un
gsp git rebase -i HEAD~N
donde N son los commits que te indica zsh
- Suele pasar que tienes cambios en local (el repo no está limpio) → hacer un
- A veces la lías con squash → reflog para hacer un reset a como estabas antes
- Utilizar Git Worktrees para poder trabajar en varias ramas a la vez, o guardar marcas en distintos archivos en distintas ramas
1.23.1. “Git’s Best And Most Unknown Feature” Worktrees
Te permite tener un directorio por cada rama
https://youtu.be/2uEqYw-N8uE
git clone --bare <repo> git worktree add [<path>] <branch> git worktree list git worktree remove <branch> # Does not remove if you have unstaged changes
1.23.2. Utilizar diff3 en vez de diff2
1.23.3. Arhcivos comunes
Puedo utilizar lo de Crear un sistema de gestión de paquetes comunes a varios venv, jdupes/ostree para estos mismos archivos comunes, e incluso para el propio entorno virtual que al final va a ser el mismo lo ejecute donde lo ejecute (asumiendo que utilizo zpy por ejemplo)
1.23.3.1. Añadir hooks para copiar archivos comunes
Archivos de configuración, credenciales, etc
Cada vez que abres una rama quieres que sean siempre los mismos y si eso cambiarlos para probar una cosa rápidamente y luego volver a la versión normal
Se puede implementar con links simbólicos a las carpetas necesarias, y luego tener un atajo rápido para poder editarlas sin cambiar las del resto por si quieres probar una cosa rápidamente, y luego volver a correr los links simbólicos
cd credentials && ln -s ../credentials/* .
1.23.4. Añadir múltiples ramas en git worktree
echo -e "master\nrelease\ndevelop" | xargs -I _ git worktree add _
1.24. Git Alternatives
1.25. github
- Sacar todos los commits de un mismo autor
https://stackoverflow.com/questions/12174276/github-list-commits-by-author
https://github.com/search?o=desc&s=committer-date&type=Commits&q=author:torvalds - Sacar los grupos a los que pertenece un usuario
https://github.com/orgs/%7Borganization%7D/teams?query=@user - Sacar todos los issues de un usuario
https://github.com/search?o=desc&q=author:lytex&s=created&type=Issues
1.25.1. GraphQL to search forks
1.25.1.1. How to order GitHub forks by stars, watchers, commits using the GitHub API? - Stack Overflow
1.25.1.2. Explorer - GitHub Docs
1.25.2. Active github subscriptions
1.25.3. Memer Action
1.26. Github Alternatives
- https://radicle.xyz/
- https://giveupgithub.org/
- Alternative Hosting Services:
- Self-Host (or join a group that self-hosts). A few options:
- Gitea
- GitLab Community Edition (note, the GitLab Enterprise Edition, which is provided to the public on gitlab.com, is (like GitHub) trade-secret, proprietary, vendor-lock-in software)
- SourceHut
- Gitea
- Alternative Hosting Services:
1.26.1. The Move Away From Github Starter Pack
https://t.me/viviandev/354
Justification:
How to move Git Repositories (in general):
How to move (to Gitlab):
- https://docs.gitlab.com/ee/user/project/import/github.html
- https://docs.gitlab.com/ee/development/github_importer.html
The advantages of Self Hosting your Repository and what to use to do so:
- https://stackoverflow.com/questions/33740369/which-are-the-pros-and-cons-of-self-hosting-your-repositories-in-other-words
- https://gitea.io/en-us/
- https://about.gitlab.com/installation/
- https://www.mercurial-scm.org/wiki/Kallithea
Another Version Control System, Mercurial:
1.26.2. Edward Loveall - Let’s Make Sure Github Doesn’t Become the only Option
https://www.reddit.com/r/programming/comments/135set8/lets_make_sure_github_doesnt_become_the_only/
git and GitHub’s symbiosis are holding us back as an industry.
GitHub is what most people use because it makes the complexities of git easier. git remains dominant despite it being complex because it’s not in the interest of GitHub and most of GitHub’s competitors to support anything else.
Other version control software exists that doesn’t need a separate company to make the code accessible from the web or makes dealing with conflicts easier. We as an industry cannot benefit from these alternatives if we continue to use GitHub this heavily.
1.27. Tools for Git Analysis
- hercules Estadísticas avanzadas de git (hay hacer
alias labours
“python3 -m labours”= porque por defecto pilla el python2, y luego también se les olvida el pipe:.
Funciona con versiones antiguas de python (3.6, 3.7), si no te tienes que compilar tú tus paquetes con dependencias binarias hercules --burndown --burndown-people file://$PWD | labours -m overwrites-matrix
- https://github.com/augmentable-dev/askgit Queries sql contra git (renombrado https://github.com/mergestat/mergestat)
- Funciona con docker:
docker run --rm -v `pwd`:/repo:ro augmentable/askgit "SELECT path FROM files limit 10"
- Funciona con docker:
- AmrDeveloper/GQL: Git Query language is a SQL like language to perform queries on .git files with supports of most of SQL features such as grouping, ordering and aggregations functions
- acaudwell/Gource: software version control visualization
- forgit
git + fzf - Git History (GitHub, GitLab, BitBucket): Quickly browse the history of files in any git rep
- 20+ tools to help you mine and analyze GitHub and Git data
- chaoss/augur: Python library and web service for Open Source Software Health and Sustainability metrics & data collection. You can find our documentation and new contributor information easily here: https://chaoss.github.io/augur/ and learn more about Augur at our website https://augurlabs.io
- cregit/cregit
- chaoss/grimoirelab: GrimoireLab: toolset for software development analytics
- chaoss/augur: Python library and web service for Open Source Software Health and Sustainability metrics & data collection. You can find our documentation and new contributor information easily here: https://chaoss.github.io/augur/ and learn more about Augur at our website https://augurlabs.io
1.28. Pitfalls & Gotchas
- Cuando haces checkout de un commit anterior en una rama, no se aplica en los merges que hagas contra esas ramas
1.29. Git en profundidad
1.29.1. git add
1.29.2. git commit
- Commit con el mismo mensaje que el anterior:
git commit -C HEAD
--amend
para enmendar un commit anterior
1.29.3. git log
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
git log --abbrev-commit --name-only
muestra hash abreviado y nombre de archivos cambiados- https://devhints.io/git-log-format
git --no-pager lg --no-color -S 18:15 -p
--no-pager
elimina el paginado estilo less--no-color
quita los caracteres de escape para los colores
git log --pretty=format
Opción | Descripción |
---|---|
%H/%h |
Commit largo/abreviado |
%an/%ae |
Author name/email |
%ad/ar |
Author date/relative date |
%s |
Subject (commit message) |
%n |
Salto de línea |
Las a
se pueden cambiar por c
para mostrar el commiter name y demás.
Commiter es el que hace el commit y author el que escribe el código.
Normalmente coincide, pero al hacer una Pull Request difiere (ya que
sólo los que trabajan en el proyecto pueden hacer commits al repositorio
principal)
- Soporta fechas con
--date
[local|short]= - strftime con
--date=format[-local]:"%Y-%m-%d %H:%M:%S"
--graph
para que se vean las ramas separarse y juntarse
1.29.3.1. filtros
--[since|after], --[until|before]
--author, --committer
--grep <mensaje>
→ el mensaje matchea. Acepta argumentos de grep como -E, pero van antes de –grep-S <codigo>
→ los commits han eliminado o añadido código que matchea-G <regex>
→ lo mismo con regex-L :func:script.py
→ Dentro de script.py, cambios hechos a la función/clase func-L <start>,<end>:script.py
→ Dentro de script.py, cambios hechos a as líneas entre <start> y <end>git log --author='^(?!Adam|Jon).*$' --perl-regexp
Regexp de perl para filtrar todos los commits de los usuarios que no son Adam ni Jon, con negative lookahead
https://stackoverflow.com/questions/4259996/how-can-i-view-a-git-log-of-just-one-users-commits
1.29.3.2. Buscar archivos en el histórico
- Por nombre de archivo
git log --all --full-history -- "**/thefile.*" git branch -a --contains 55d2069 # Para ver en qué rama está
git lg -S"#+transclude" -p -- . ":\!path/to/file"
- Por línea
git grep <regexp> $(git rev-list --all) git grep <regexp> $(git rev-list --all -- lib/util) -- lib/util # Buscar en un subárbol
git log -S<string> git log -G<regex>
1.29.4. git merge
Git: Handling Merge Conflicts Using “Ours” and “Theirs” - Howchoo
tl;dr
–ours –theirs has been changed as of git 2.40
Withfeature
branch checked out.
git merge master
git rebase master
Keep changes from master
-Xtheirs
-Xours
Keep changes from feature
-Xours
-Xtheirs
- Squash, Merge, or Rebase? — Matt Rickard
1.29.5. git grep
git grep -n # Saca el número de línea y es clickable en vscode git grep buscar -- "*.py" # los "" son necesarios, si no falla git grep -i task -- './*' ':(exclude)*.md' # Buscar excluyendo los .md git grep -i task -- './*' ':!*.md' # Buscar excluyendo los .md
1.29.6. cherry picking y diff apply
- git cherry-pick no aplica sólo un commit, sino que mueve el HEAD hacia ese commit (lo que puede provocar conflicto de merge aunque en el commit específico que coges no haya dichos conflictos)
- La alternativa es diff-apply
git diff d892531 815a3b5 | git apply
1.29.7. On undoing, fixing, or removing commits in git
git rebase --rebase-merges --onto SHA^ SHA
1.29.9. Información
git show-branch (|-r|-a)
Muestra todas las ramas
locales|remotas|todasgit blame <archivo>
Muestra quién ha escrito cada línea de <archivo>
1.29.10. Configuración
/etc/gitconfig -> --system --system-wide
~/.gitconfig or ~/.config/git/config -> --global
repo/.git/config -> --local
1.29.10.1. .gitignore
- Es un archivo para hacer una lista de los archivos que no se tienen
que seguir (track), es decir, git ignorará esos archivos y no se
añadiran incluso tras hacergit add *
git add -f <archivo>
fuerza añadir el archivo incluso si está
ignorado en.gitignore
git config --local core.excludesfile hidden/.gitignore_local
1.29.11. remotes
git branch --set-upstream-to=origin/master master
enlaza origin/master
con tu master local, de manera que no hay que hacer
git push origin master
o git pull origin master
1.29.11.1. Crear un repositorio
server:$ git init --bare --shared
local:$ git clone <repo url>
1.29.11.2. Submódulos de git
git submodule add <url>
git submodule update --init
cd
al repo ygit pull
para coger el último cambiogit submodule update
para quedarte up to date con el repo original
1.29.12. Herramientas
1.29.12.1. diff
git diff <x> <x+∆x>
Si sólo ponemos un commit y no tenemos ningún
unstaged changes/untracked files, entonces git diff <x>
es lo mismo
que git diff <x> HEAD
https://stackoverflow.com/questions/31454603/order-of-commit-arguments-in-git-diff
1.29.12.2. stash
git stash git stash list; git stash apply @stash{2}; git stash pop # aplica el primero git stash --keep-index (stash sin checkout a la rama) --include-untracked (-u) git stash branch <branch> # Nueva rama para el stash git stash push -m "mensaje de stash" -- <pathspec>
1.29.12.3. patchs, interactivo
git add -i # abre modo interactivo # patch -> ciertas partes del código, añadir ciertas líneas git add --patch git checkout --patch git stash push --patch
1.29.12.4. grep
git grep -n (número de línea) -c (contar ocurrencias) -p (en qué parte del código) <regex> -- <pathspec>
1.29.12.5. rev-list
git rev-list <inicio>..<final> # Saca todos la lista de commits de inicio a final