8. Best Practices and Special Cases
To finish, let's list some tips that will come in handy in your day-to-day work with Git.
Atomic and well-documented commits
An atomic commit does ONE thing and does it well.
❌ Bad commit:
git commit -m "various fixes"
# Changes: fixes a bug, adds a feature, updates docs, refactors code
✅ Good commit:
git commit -m "fix: fix authentication error on login"
# Only changes related to the authentication bug
git commit -m "feat: add export to CSV button"
# Only the export button
git commit -m "docs: update installation guide"
# Only documentation
Writing good commit messages
By convention, a good commit message has the following structure:
type(scope): short description (50 chars max)
More detailed explanatory body (72 chars per line).
Explain WHAT and WHY, not how.
It can have multiple paragraphs.
- Bullet points are fine too
- Use a hyphen or asterisk
References to issues at the end.
Fixes #123
See also #456, #789
For example:
feat(auth): add OAuth authentication
Implements authentication using OAuth 2.0 to allow
login with Google and GitHub.
Changes:
- Add passport-oauth2 dependency
- Create authentication middleware
- Update login routes
- Add integration tests
This feature was requested by multiple users
and will improve the onboarding experience.
Fixes #234
Related to #189
According to Tim Pope there are 7 rules for writing good commit messages:
- Separate the subject from the body with a blank line
- Limit the subject to 50 characters
- Capitalize the subject
- Do not end the subject with a period
- Use the imperative mood in the subject
- Wrap the body at 72 characters
- Use the body to explain what and why, not how
You don't need to follow them all to the letter, but keeping them in mind will improve the quality of your commits.
Keeping a clean history
git rebase: Rewrites the commit history.
# Interactive rebase of the last 3 commits
git rebase -i HEAD~3
You'll see something like:
pick a1b2c3d feat: add login
pick e4f5g6h fix: fix typo
pick i7j8k9l refactor: clean up code
# Available commands:
# p, pick = use commit
# r, reword = use commit, but edit the message
# e, edit = use commit, but stop to amend
# s, squash = use commit, but merge with the previous one
# f, fixup = like squash, but discard the message
# d, drop = remove commit
Useful for:
- Combining related commits
- Editing commit messages
- Reordering commits
- Removing unnecessary commits
NEVER rebase commits already pushed to main or shared with others.
git stash: Save changes temporarily
In some cases you need to switch branches, sync it, but you have uncommitted changes. git stash lets you save those changes temporarily and recover them later.
# You have uncommitted changes but need to switch branches
git status
# modified: file.js
# Save changes temporarily
git stash
# Now you can switch branches
git switch other-branch
# When you come back
git switch my-branch
git stash pop # Recovers and removes from the stash
# View saved stashes
git stash list
# Apply without removing
git stash apply
# Save with a message
git stash save "WIP: implementing feature X"
# Clear all stashes
git stash clear
An alternative would be to create a temporary branch, commit there, and then merge or rebase it later.
git reset: Undo changes
You can undo changes at different levels: unstage, undo commits, or undo EVERYTHING.
# Undo staging (keeps changes in files)
git reset HEAD file.js
# Undo the last commit (keeps changes in files)
git reset HEAD~1
# Undo the last commit (keeps changes in staging)
git reset --soft HEAD~1
# Undo EVERYTHING (DANGEROUS!)
git reset --hard HEAD~1
Differences:
--soft: Undoes the commit, changes stay in staging. Your files are ready to be committed again.--mixed(default): Undoes the commit and staging, changes in the working directory. Your files stay modified but not staged.--hard: Undoes EVERYTHING, the changes are lost. Your files return to the state of the commit.
git revert: Undo commits safely
If you've pushed, or synced, your changes with GitHub (or a Git host) and need to undo a commit, you can fix it with git revert. It creates a new commit that "undoes" the changes of the previous commit. It will be visible in the history and won't cause problems for other collaborators.
# Undo a specific commit
git revert abc1234
# Undo multiple commits
git revert abc1234..def5678
# Revert without creating a commit automatically. Useful for grouping several reverts into one.
git revert -n abc1234
git cherry-pick: Apply specific commits
Used to merge a specific commit from one branch to another without needing to do a full merge.
# Apply a commit from another branch
git cherry-pick abc1234
# Apply several commits
git cherry-pick abc1234 def5678
# Apply a range
git cherry-pick abc1234..def5678
The most common use is to apply bug fixes. There's a commit on the develop branch that fixes a critical bug and you want to apply it to the main branch without merging all the development work.
Keeping your fork up to date
# Add upstream (if you haven't already)
git remote add upstream git@github.com:original/repo.git
# Fetch changes
git fetch upstream
# Update your local main
git switch main
git merge upstream/main
# Update your fork on GitHub
git push origin main
# Update a feature branch
git switch feature/my-feature
git merge main
# or better
git rebase main
This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.
Desafíos de programación atemporales y multiparadigmáticos
Te encuentras ante un librillo de actividades, divididas en 2 niveles de dificultad. Te enfrentarás a los casos más comunes que te puedes encontrar en pruebas técnicas o aprender conceptos elementales de programación.
Buy the bookWill you buy me a coffee?
This is how I keep writing without ads or paywalls.
Sure, it's on me!
Comments
There are no comments yet.