What is HEAD in Git?
In Git, HEAD is a pointer to the latest commit in the current branch. It tells Git which commit you’re currently working on.
Types of HEAD States:
- Normal (Attached HEAD)
WhenHEADpoints to the latest commit in a branch, it’s called an attached HEAD.
# show commits in single line with message
git log --oneline --graph
* 07cf493 (HEAD -> main, origin/main) feat: Implement tailwind css to product pages
* c3ee7d4 feat: Add images to products
* e342472 feat: Install tailwind css
* 40fc222 first commit
- Detached HEAD
If you check out a specific commit (not a branch),HEADbecomes detached.
โ git checkout c242462
# undo detached HEAD
โ git switch -
# or go back to main
โ git checkout main
Common HEAD Uses in Commands
- Reset Last Commit (Undo Latest Commit, Keep Changes)
git reset HEAD~1
HEAD~1 means “one commit before HEAD” (previous commit). This unstages the latest commit but keeps changes.
2. Unstage a Staged File
git reset HEAD filename
Removes filename from staged state but keeps changes.
3. Move HEAD to a Different Commit (Soft Reset)
git reset --soft HEAD~2
Moves HEAD back two commits but keeps all changes staged.
4. Hard Reset (Undo Everything, No Recovery)
git reset --hard HEAD~1
Moves HEAD one commit back and deletes all changes.
5. View HEAD Commit Hash
git rev-parse HEAD
Shows the exact commit hash HEAD is pointing to.
HEADis simply Git’s way of tracking where you are in the commit history. It allows you to navigate, reset, and control commits efficiently.
Git useful commands โ
# compare 2 commits to see what is changed from one to another
git diff e144462 c4ed9d4
# To ignore all changes in the working directory and reset it to match the latest commit
git restore .
# If You Also Want to Remove Untracked Files
git clean -fd
# completely wipe all changes in the working directory
git restore . && git clean -fd
# move uncommitted file into a special area
git stash
# get back the unstaged files into working tree
git stash pop
# other commands
git stash save "Add tailwind to product show"
git stash list
git stash pop stash@{2}
git stash show
git stash apply
# If you decide you no longer need a particular stash, you can delete it with git stash drop
git stash drop stash@{1}
# or you can delete all of your stashes with:
git stash clear
To get the new changes from the remote repo to your local repo do the following command:
git fetch
but remember this does not update your working directory. git fetch allows you to check the incoming commits using git log and you can merge those changes to your current branch using git merge.
git fetch + git merge = git pull
If all goes well without any code conflict with git pull your code is updated to Local Repo and Working directory. (Your branch is Fast-Forwarded)

When Do Stash and Pull Interact?
The connection arises in real-world workflows when you need to pull remote changes but you have local uncommitted work:
Scenario:
- Youโre working on a branch (
main) with uncommitted changes. - You need to pull updates from the remote (
git pull), but Git blocks this if your working directory is dirty (has uncommitted changes). - To resolve this, you:
- Stash your changes (
git stash) โ clears the working directory. - Pull the updates (
git pull). - Reapply your stash (
git stash pop) to merge your changes with the newly pulled updates.
- Stash your changes (
Git commit message:Best practices ๐
1. Follow the Conventional Format
A well-structured commit message consists of:
- A short summary (50 characters max)
- A blank line
- A detailed description (if necessary, up to 72 characters per line)
Example:
git commit -m "feat: Add user authentication with Devise" -m "Implemented Devise for user authentication, including:
- User sign up, login, and logout
- Email confirmation and password recovery
- Integration with Turbo Streams
Closes #42"
feat: Add user authentication with Devise
Implemented Devise for user authentication, including:
- User sign up, login, and logout
- Email confirmation and password recovery
- Integration with Turbo Streams
Closes #42
Explanation:
- The first
-margument contains the commit title (short summary, 50 characters max). - The second
-margument contains the detailed description, with each bullet point on a new line. - The
Closes #42automatically links and closes GitHub/GitLab issue #42 when pushed.
Alternative Using a Text Editor (Recommended for Long Messages)
If your commit message is long, use:
git commit
This opens the default text editor (like Vim or Nano), where you can structure the message properly:
feat: Add user authentication with Devise
Implemented Devise for user authentication, including:
- User sign up, login, and logout
- Email confirmation and password recovery
- Integration with Turbo Streams
Closes #42
This keeps the message clean and readable. ๐
2. Use a Clear and Concise Subject Line
- Limit the first line to 50 characters.
- Start with an imperative verb (e.g., “Add”, “Fix”, “Refactor”, “Improve”).
- Avoid generic messages like “Update” or “Fix bug”.
โ Good:
fix: Resolve N+1 query issue in orders controller
โ Bad:
Fixed bug
3. Use Conventional Commit Types
Use prefixes to categorize the change:
feat:โ New featurefix:โ Bug fixdocs:โ Documentation updatestyle:โ Code formatting (no logic change)refactor:โ Code refactoring (no feature change)test:โ Adding/modifying testschore:โ Maintenance tasks (e.g., dependencies, build scripts)perf:โ Performance improvementci:โ CI/CD-related changes
Example:
perf: Optimize database queries for dashboard stats
4. Include Context and Motivation
Explain why a change was made if it’s not obvious.
โ Good:
refactor: Extract user authentication logic to service object
Moved authentication logic from controllers to a dedicated
service object to improve testability and maintainability.
5. Reference Issues and PRs
- Use
Closes #123to automatically close the issue. - Use
Refs #456if it’s related but not closing the issue.
Example:
feat: Implement image upload in profile settings
Users can now upload profile pictures. The uploaded images
are stored using Active Storage.
Closes #89
6. Keep Commits Small and Focused
Each commit should:
- Represent a single logical change.
- Avoid mixing refactoring with new features.
โ Good:
- Commit 1:
refactor: Extract helper method for API requests - Commit 2:
feat: Add API endpoint for fetching user statistics
โ Bad:
- Commit 1:
feat: Add API endpoint and refactor helper methods
7. Use Present Tense
Write commit messages in present tense, not past tense.
โ Good:
fix: Handle nil values in user profile settings
โ Bad:
Fixed nil values issue in user profile settings
Following these best practices ensures readable, maintainable, and searchable commit history. ๐