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:

  1. Separate the subject from the body with a blank line
  2. Limit the subject to 50 characters
  3. Capitalize the subject
  4. Do not end the subject with a period
  5. Use the imperative mood in the subject
  6. Wrap the body at 72 characters
  7. 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

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 book

Will you buy me a coffee?

This is how I keep writing without ads or paywalls.

Comments

There are no comments yet.