Learn Version Control with Git: A Practical Guide to Commands and Workflows
If you've ever worked on a project and wished you could go back to a previous version, track your changes, or collaborate seamlessly with others, Git is a tool worth learning. While Git is a cornerstone in the software development world, it is just as useful for writers, researchers, students, designers, or anyone managing files and revisions over time.
In this article, you'll learn:
- What Git is and how it works
- The practical benefits of using Git
- Common terminology made easy to understand
- Essential Git commands explained clearly
- Real-world workflows to help you get started
By the end, you’ll be confident using Git for personal or professional projects, with a clear understanding of how to version and manage your work effectively.
What It Is #
Git is a version control system. It helps you track and manage changes to files over time. Think of it like a save button for your entire project, but with a history. You can go back to previous versions, see what changed, who made the changes, and when.
Git is distributed, meaning every user has a full copy of the project history. This makes collaboration easier and safer. You can work on new ideas, fix problems, or test changes without affecting the main project until you're ready.
Git handles all types of files, not just code. It’s ideal for:
- Writing projects (e.g., articles, books)
- Research notes
- Personal documents
Git is not well suited for large binary files like images or videos, as it cannot efficiently track changes in them. For such files, consider using specialised tools like Git Large File Storage (Git LFS) or dedicated asset management systems.
In short, Git lets you:
- Save your work often
- Revert mistakes
- Collaborate smoothly
- Experiment safely
It’s like having an undo button, timeline, and backup system all in one.
Key Features
- Version control: Keep a detailed history of every change. You can view edits, compare versions, and roll back to earlier states if needed.
- Branching: Create separate environments to work on new features, fix issues, or test ideas. All without affecting your main files.
- Merging: Combine changes from different branches into one final version. Git helps detect and resolve conflicts along the way.
- Distributed system: Every user has a complete copy of the project, including its full history. You don’t need a central server to work or access previous versions.
Why Use It
- Reliability: Since all data is stored locally as well as remotely, your work is safe even if a server fails or you're offline.
- Speed: Most actions (saving changes, viewing history, switching versions) are performed on your local machine, making Git extremely fast.
- Collaboration: Git makes teamwork seamless. Multiple people can work on different parts of a project at the same time using branches, then merge their work together without overwriting each other.
- Auditability: Every change is recorded with the author's name, date, and a short message describing what was done. This makes it easy to track who changed what and why.
GitHub
GitHub is a cloud-based hosting platform for Git repositories. It adds powerful features for team-based development and project automation, including:
- Pull requests and code reviews to discuss and approve changes
- CI/CD pipelines such as GitHub Actions to automate testing and deployment
- Issue tracking for bug reports, tasks, and feature requests
- Project management tools like boards, milestones, and labels
Typical Workflow
Developers commonly follow this pattern:
- Use Git locally to write and manage code on their own machine
- Push to GitHub to collaborate with others, share progress, and automate workflows
This separation allows Git to handle version control and GitHub to handle collaboration, visibility, and automation.
Terminology #
Repository (Repo)
A repository is a project folder managed by Git. It contains your files and all the information Git needs to track and manage changes over time.
Key Components
- Project files – your actual content (e.g. code, documents)
.git/
directory – a hidden folder that stores:- Complete version history
- Change tracking metadata
- Configuration settings
Types of Repositories
- Local repository
- Stored on your own machine
- Lets you work offline
- Includes full project history
- Remote repository
- Hosted on a server (e.g. GitHub)
- Used for collaboration and backup
- Acts as the shared source of truth
Typical Workflow
- Clone a remote repository to your machine
- Pull updates from the remote when others make changes
- Push your changes to the remote to share your work
Working Directory
The working directory is the folder on your computer where you actively edit your files. It’s what you see and interact with directly.
Key Points
- Definition: The folder where you make changes to your project files
- Example: If you open
~/dotfiles
, you are working in that directory
Git does not track your edits here until you stage them. Changes remain untracked or modified until added with git add
.
Staging Area (Index)
The staging area (also called the index) is a space where you prepare changes before permanently saving them in the repository. It acts like a checklist: you choose which changes to include in the next commit.
Key Points
- Purpose: Gives you control over what goes into each commit
- Use case: Useful when you want to commit only some of your changes, not all at once
- Command:
git add <file>
This command adds specific changes to the staging area.
Workflow Example
- You edit several files
- Use
git add
to select the ones you want to include - Then run
git commit
to save only those selected changes to the repository
This lets you group related changes logically and keep your history clean and understandable.
Commit
A commit is a snapshot of your project at a specific point in time. It records what was changed, by whom, and why. Each commit creates a permanent entry in the project history, allowing you to revisit, compare, or restore past versions.
What a Commit Includes
- A unique ID (called a SHA hash)
- Author information (name and email)
- A commit message describing the change
Command
git commit -m "<message>"
This saves the staged changes with a clear message explaining what you did. Commits help you track progress and keep your work organised. A good commit message makes it easier to understand what changed and why.
Branch
A branch is a lightweight pointer to a sequence of commits. It lets you work on new features, fixes, or experiments without affecting the main project.
Branches are key to safe and organised development. You can switch between them, develop separately, and merge your work when it’s ready.
Key Points
- Purpose: Isolate work so the main project remains stable
- Default branch: Usually named
main
ormaster
- Command:
git branch <branch>
Use branches to:
Develop features independently
Fix bugs without interrupting other work
Experiment freely, knowing the main version stays untouched
Once finished, you can merge the branch back into the main project.
Merge
Merging is the process of combining changes from one branch into another. It brings together work done in separate branches so the project stays unified.
Git attempts to merge automatically. If two branches changed the same part of a file, Git will ask you to resolve the conflict manually.
Key Points
- Purpose: Integrate work from different branches
- Common use: Combine a finished feature branch into the
main
branch - Command:
git merge <branch>
This merges the specified branch into your current branch.
Example Workflow
1. Switch to the branch you want to merge into:
git checkout main
2. Merge the feature branch:
git merge feature-login
Always review changes before merging
Use branches to keep features isolated, then merge when stable and tested
Conflict
A conflict happens when Git cannot merge changes automatically because the same part of a file was modified differently in two branches.
What Happens
- Git stops the merge
- Marks the conflicting sections in the file
- Requires you to review and fix the differences manually
How to Resolve
- Open the conflicted file
- Look for conflict markers (
<<<<<<<
,=======
,>>>>>>>
) - Edit the file to choose or combine the changes
- Save the file
- Add the resolved file to staging:
git add <file>
Complete the merge by committing:
git commit -m "<message>"
Resolving conflicts carefully ensures your project stays consistent and all changes are accounted for.
Remote
A remote is a version of your repository hosted on another server or service, such as GitHub. It allows you to:
- Share your work with others
- Backup your project online
- Collaborate from different locations
Key Points
- Acts as a central copy of your project
- Synchronises changes between your local repository and the remote
Command:
git remote add origin <url>
This command connects your local repository to a remote repository, typically named origin
.
After setting this up, you can:
- Push your changes to the remote
- Pull updates from the remote to your local copy
Clone
Cloning means downloading a complete copy of a remote repository to your local computer.
Key Points
- Used once to get the project files and full history locally
- Sets up a local repository linked to the remote
Command
git clone <url>
Example:
git clone https://github.com/user/project.git
This creates a local folder with all the files and version history, ready for you to work on.
Pull
Pulling means fetching changes from the remote repository and merging them into your local copy.
Key Points
- Keeps your local repository up to date with the remote repository
- Combines two actions:
- Fetch: Download changes
- Merge: Integrate changes into your current branch
Command
git pull
Use this regularly to ensure your local files reflect the latest remote updates before starting new work.
Push
Pushing means sending your local commits to the remote repository.
Key Points
- Updates the remote repo with your changes
- Shares your work with others
- Usually done after committing locally
Command
git push
Use this to upload your latest commits so others can access them and collaborate.
Fetch
Fetching downloads new commits and updates from the remote repository but does not merge them into your local branch.
Key Points
- Retrieves changes without changing your working files
- Lets you review updates before integrating them
- Keeps your local copy aware of remote progress
Command
git fetch
After fetching, you can inspect changes and decide when to merge or rebase them into your work.
HEAD
HEAD is a pointer that references the current commit or branch you are working on.
Key Points
- Indicates your current position in the project history
- Moves as you switch branches or check out commits
- Shows the latest commit in your working directory
Commands Related to HEAD
View current commit and history:
git log
The top entry is where HEAD points.
Change HEAD to a different commit or branch:
git checkout <commit>
or
git switch <branch>
HEAD helps Git know which snapshot you are currently working with.
Reset
Reset moves the HEAD pointer to a specific commit and can optionally update your staging area and working files.
Types of Reset
Reset Type | Description | Effect on Changes |
---|---|---|
--soft |
Moves HEAD to the chosen commit | Keeps changes staged (ready to commit) |
--mixed default |
Moves HEAD to the chosen commit | Unstages changes but keeps them in working directory |
--hard |
Moves HEAD to the chosen commit | Discards all changes in staging and working directory (irreversible) |
Use Cases
- Undo commits but keep changes (
--soft
) - Unstage changes but keep edits (
--mixed
) - Completely reset to a clean state (
--hard
)
Example:
git reset --hard HEAD~1
This moves HEAD back one commit and deletes all changes made since then. Use with caution.
Revert
Revert creates a new commit that undoes the changes introduced by a previous commit, without altering the project history.
Key Points
- Safely reverses changes in shared branches
- Does not delete or rewrite history like
reset
- Preserves collaboration integrity by adding a “fix” commit
Use Case
Use git revert
when you want to undo a change but keep the commit history intact, especially when working with others.
Command:
git revert <commit_hash>
Workflow
1. Display commit history:
git log --oneline
Output example:
e3a1f45 fix: broken image path
b2d3c7a add: user authentication
7f9e5a1 Initial commit
The left part (e.g. e3a1f45
) is the commit hash, used to identify a specific commit.
2. Identify and copy the commit hash you want to revert
3. Run revert:
git revert <commit_hash>
This creates a new commit that reverses the changes introduced by the specified commit, preserving history.
Checkout
This checkout command lets you change branches or restore files from a specific commit.
Key Points
- Switch branches to work on different lines of development
- View past versions of your project by checking out a specific commit (detached HEAD state)
Commands
Switch to a branch:
git checkout <branch>
View a past commit (detached HEAD state):
git checkout <commit>
Using git checkout
helps you navigate your project’s history and switch between tasks efficiently.
Log
The log command lets you view the commit history of your project.
Key Points
- Shows a timeline of all commits
- Helps track what changed, when, and by whom
Commands
Detailed commit history:
git log
Summary view with one line per commit:
git log --oneline
Use the log to understand your project’s progression and review past changes efficiently.
Diff
The diff command shows the differences between files or commits, helping you see what has changed.
Key Points
- Compare unstaged changes against the last commit
- Compare staged changes ready to be committed
- Compare differences between two commits
Commands
Show unstaged changes:
git diff
Show staged changes (what’s ready to commit):
git diff --staged
Show differences between commits:
git diff HEAD~1 HEAD
Use git diff
to review edits before committing or merging.
Stash
Stash lets you temporarily save changes that you aren’t ready to commit yet, so you can switch tasks or branches without losing work.
Key Points
- Saves your current changes aside safely
- Allows you to work on something else
- Later, you can reapply the saved changes
Commands
Save your changes:
git stash
Reapply saved changes:
git stash apply
Stashing is useful when you need a clean working directory but want to keep your unfinished work for later.
Tag
A tag is a label you attach to a specific commit to mark important points in your project, such as releases or milestones.
Key Points
- Marks a commit with a meaningful name
- Commonly used to identify versions (e.g., v1.0, v2.1)
- Tags are easy to reference later
Command
git tag v1.0
This command tags the current commit as v1.0
. You can also tag earlier commits by specifying their ID.
.gitignore
Always set up a .gitignore
file to exclude sensitive files (e.g., credentials, keys, config files) from your repository. This prevents accidental publishing of sensitive information on GitHub or other remote platforms. Double-check your .gitignore
before pushing changes.
The .gitignore
file tells Git which files or folders to ignore and not track in the repository.
Key Points
- Prevents unnecessary or sensitive files from being committed
- Uses patterns to specify files or directories to exclude
Example
# Backup files
*.bak
# Logs and temporary files
*.log
*.tmp
# Editor and project configuration
.prettierignore
.prettierrc
.vscode/
.workspace
# Git-related files
.gitignore~
.git/
# OS and system files
.DS_Store
.Spotlight-V100
.Trashes
# Secrets and credentials
*.key
*.pem
Using .gitignore
keeps your repository clean and secure.
.gitmessage
The .gitmessage
file defines a custom commit message template to guide how you write commit messages in Git.
Key Points
- Helps maintain consistent, readable commit messages
- Acts as a template when using
git commit
(especially without-m
) - Can be used globally or on a per-project basis
Examples
# Commit Message Guidelines
# Commit message should complete the sentence:
# “If applied, this commit will...”
# Summary line:
# - Max 50 characters, no punctuation
# - Format: <type>: <keyword> <summary>
# Example:
docs: add installation instructions to readme
# Commit Types:
# - chore: Maintenance or deletions
# - docs: Documentation only
# - feat: New feature
# - fix: Bug fix
# - perf: Performance improvement
# - refactor: Code change without behaviour change
# - revert: Revert a previous commit
# - style: Formatting (whitespace, comments)
# - test: Adding or updating tests
# Commit Keywords:
# - add: Introduce new content
# - clean: Simplify or remove unused code
# - disable: Turn off a setting or feature
# - document: Improve comments or documentation
# - enable: Turn on a setting or feature
# - fix: Correct broken or buggy behaviour
# - format: Adjust spacing or formatting
# - move: Relocate items
# - refactor: Restructure without changing behaviour
# - remove: Delete or deprecate
# - rename: Rename items
# - update: Modify existing content
# Optional Body (wrap at 72 characters):
# - Explain what and why, not just how
# - Provide context for future maintainers
# - Link related issues or tickets
# Optional Footer:
# - Closes #123
# - Co-authored-by: <name> <email>
Notes:
- Lines starting with
#
are ignored by Git - A blank line is required between the title and description
Commit Message Style Guide
- Use lowercase for type and keyword (e.g.,
docs: add
) - Keep the summary short (max 50 characters), no ending punctuation
- Summaries should complete: “If applied, this commit will…”
- Use an optional body to explain what and why (wrap at 72 characters)
- Include references in the footer (e.g.,
Closes #123
) for context
Examples
Basic commit message:
docs: add installation instructions to readme
Commit message with description:
docs: add installation instructions to readme
Added a new section to the README that details step-by-step
installation instructions for the project. This will help new users
set up the environment quickly without confusion.
Closes #123
How to Use
Set globally:
git config --global commit.template ~/.gitmessage
Set per project:
git config commit.template .gitmessage
Using .gitmessage
helps enforce clear, structured commit messages, improving project maintainability and collaboration.
Essential Commands #
Repository Setup and Configuration #
Command | Description |
---|---|
git init |
Initialise a new Git repository |
git clone <url> |
Clone a remote repository |
git config --global user.name "<name>" |
Set global username |
git config --global user.email "<[email protected]>" |
Set global email address |
git config --global commit.template ~/.gitmessage |
Set global commit message template |
git config commit.template .gitmessage |
Set commit message template for current repository |
git config --list |
List all configuration settings |
Staging and Committing #
Command | Description |
---|---|
git status |
Show current working directory status |
git add <file> |
Stage a specific file |
git add . |
Stage all changes in current directory |
git commit |
Commit staged changes (open message template) |
git commit -m "<message>" |
Commit staged changes with a message |
git commit --amend |
Modify the last commit |
Branching and Merging #
Command | Description |
---|---|
git branch |
List local branches |
git branch <branch> |
Create a new branch |
git checkout <branch> |
Switch to a branch |
git checkout -b <branch> |
Create and switch to a new branch |
git checkout --orphan <branch> |
Create a new orphan branch (no commit history) |
git branch -m <new_name> |
Rename current branch |
git branch -m <old> <new> |
Rename a specific branch |
git merge <branch> |
Merge a branch into the current one |
git branch -d <branch> |
Delete a local branch |
git branch -a |
List all branches (local and remote) |
Remote Repositories #
Command | Description |
---|---|
git remote -v |
List remote repositories |
git remote remove <remote> |
Delete remote |
git remote add origin <url> |
Add a remote named origin |
git push origin <branch> |
Push changes to a remote branch |
git pull origin <branch> |
Fetch and merge from a remote branch |
git fetch |
Download changes without merging |
Viewing and Comparing #
Command | Description |
---|---|
git log |
Show commit history (press q to quit log view) |
git log --oneline |
Compact log view |
git diff |
Show unstaged changes |
git diff --staged |
Show staged changes |
git show <commit> |
Show details for a specific commit |
Undoing and Cleaning #
Command | Description |
---|---|
git reset <file> |
Unstage a file |
git reset --hard <commit> |
Reset to a specific commit (destructive) |
git checkout -- <file> |
Discard changes in working directory |
git clean -f |
Remove untracked files |
git revert <commit> |
Create a new commit to undo a previous one |
Stashing
Command | Description |
---|---|
git stash |
Stash uncommitted changes |
git stash list |
List stashed changes |
git stash apply |
Re-apply stashed changes |
git stash drop |
Delete a specific stash |
Tags
Command | Description |
---|---|
git tag |
List all tags |
git tag <name> |
Create a new tag |
git tag -d <name> |
Delete a tag |
git push origin <tag> |
Push a tag to the remote |
git push origin --tags |
Push all tags to the remote |
Workflow #
Install #
To use Git and GitHub effectively, you need to install two tools:
- Git: The core version control system to track and manage changes in your projects.
- GitHub CLI (
gh
): A command-line tool to interact with GitHub directly, enabling you to manage repositories, pull requests, issues, and more from your terminal.
Linux (Debian/Ubuntu):
sudo apt install git gh -y
macOS (using Homebrew):
brew install git gh
Verify installation:
git --version
gh --version
Authenticate GitHub CLI:
gh auth login
Follow prompts. Choose:
- GitHub.com
- Protocol: SSH
- SSH public key: skip
- Authenticate: browser
Basic Git Workflow #
A typical Git workflow follows these key steps:
# Create a new local repository
git init
# Or clone an existing remote repository
git clone https://github.com/<user>/<repo>.git
# Check the current status of your repository
git status
# Add files to the staging area
git add <file1> <file2>
# Commit staged changes with a descriptive message
git commit -m "<message>"
# View the commit history
git log
# Push your commits to the remote repository (e.g., GitHub)
git push origin main
# Pull the latest changes from the remote repository
git pull origin main
Setting Up SSH Access to GitHub #
Step 1: Check for Existing SSH Keys
Check if you already have SSH keys:
ls -l ~/.ssh
If keys exist and you want to reuse them, skip to step 3.
Step 2: Generate a New SSH Key
Generate a key using the ed25519
algorithm:
ssh-keygen -t ed25519 -C "<[email protected]>" -f ~/.ssh/<key_name>
Key name example: github
Step 3: Add SSH Key to Agent
Linux
Start the SSH agent (if not already running):
eval "$(ssh-agent -s)"
Add private key:
ssh-add ~/.ssh/<key_name>
macOS
Make the key persist across reboots and login sessions:
ssh-add --apple-use-keychain ~/.ssh/<key_name>
This:
- Adds the key to the agent
- Stores the passphrase in the keychain
Step 4: Edit SSH Config
Open SSH config:
vim ~/.ssh/config
Linux
GitHub accepts SSH connections only on ports 22
and 443
(via ssh.github.com). Custom ports are not supported.
Add:
Host github.com
HostName ssh.github.com
Port 443
User git
IdentityFile ~/.ssh/<key_name>
IdentitiesOnly yes
Set permissions:
chmod 600 ~/.ssh/config
Verify permissions:
ls -l ~/.ssh/config
macOS
Add:
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/<key_name>
IdentitiesOnly yes
UseKeychain yes
AddKeysToAgent yes
Explanation:
Directive | Description |
---|---|
Host github.com |
Alias used in SSH commands and Git remotes. |
HostName github.com |
Actual hostname to connect to. |
User git |
Required SSH user for GitHub access. |
IdentityFile ~/.ssh/<key_name> |
Path to your private SSH key. |
IdentitiesOnly yes |
Use only the specified key, not others loaded in the agent. |
UseKeychain yes |
Store key passphrase in the system keychain (macOS only). |
AddKeysToAgent yes |
Automatically add the key to the SSH agent (macOS only). |
Step 5: Copy Public Key to Clipboard
Display public key:
cat ~/.ssh/<key_name>.pub
Use this output to add the key to your GitHub account.
Step 6: Add SSH Key to GitHub
- Go to GitHub → Settings → SSH and GPG keys
- Click New SSH key
- Add:
- Title:
<device>-<location>-github
- Key type: authentication key
- Key: *** (paste your public SSH key here)
- Click "Add key" to save
- Title:
SSH key title examples:
imac-home-github
desktop-work-github
linode-website-github
Step 7: Test Connection to GitHub
ssh -T [email protected]
If prompted the first time, type yes
to accept GitHub’s SSH fingerprint.
You should see:
Hi <user>! You've successfully authenticated, but GitHub does not provide shell access.
Step 8: Configure Git
Set identity:
git config --global user.name "<name>"
git config --global user.email "<[email protected]>"
Verify Git config:
git config --list
Press q
to exit.
Setting Up a Git Repository #
Step 1: Initialise Local Repository
mkdir -p <path/to/repo>
cd <path/to/repo>
git init
This creates a .git
folder which tracks all changes.
Step 2: Create .gitignore
Create file:
vim .gitignore
Add:
# Backup files
*.bak
# Logs and temporary files
*.log
*.tmp
# Editor and project configuration
.prettierignore
.prettierrc
.vscode/
.workspace
# Git-related files
.gitignore~
.git/
# OS and system files
.DS_Store
.Spotlight-V100
.Trashes
# Secrets and credentials
*.key
*.pem
Step 3: Set Up Commit Message Template
Create file:
vim ~/.gitmessage
Add:
# Commit Message Guidelines
# Commit message should complete the sentence:
# “If applied, this commit will...”
# Summary line:
# - Max 50 characters, no punctuation
# - Format: <type>: <keyword> <summary>
# Example:
docs: add installation instructions to readme
# Commit Types:
# - chore: Maintenance or deletions
# - docs: Documentation only
# - feat: New feature
# - fix: Bug fix
# - perf: Performance improvement
# - refactor: Code change without behaviour change
# - revert: Revert a previous commit
# - style: Formatting (whitespace, comments)
# - test: Adding or updating tests
# Commit Keywords:
# - add: Introduce new content
# - clean: Simplify or remove unused code
# - disable: Turn off a setting or feature
# - document: Improve comments or documentation
# - enable: Turn on a setting or feature
# - fix: Correct broken or buggy behaviour
# - format: Adjust spacing or formatting
# - move: Relocate items
# - refactor: Restructure without changing behaviour
# - remove: Delete or deprecate
# - rename: Rename items
# - update: Modify existing content
# Optional Body (wrap at 72 characters):
# - Explain what and why, not just how
# - Provide context for future maintainers
# - Link related issues or tickets
# Optional Footer:
# - Closes #123
# - Co-authored-by: <name> <email>
Configure Git to use it:
git config --global commit.template ~/.gitmessage
Verify Git configuration:
git config --list
Press q
to exit.
Step 4: Commit Files
git add .
git status
git commit
git add .
: Stages all tracked and untracked files, excluding.gitignore
entriesgit commit
: Launches editor with.gitmessage
template
Default First Commit
Use the message:
Initial commit
- Marks the first commit in a new repository
- Common convention to indicate project start
Step 5: Create and Link Remote Repository (GitHub CLI)
gh repo create <user>/<repo> --private --source=. --remote=<remote> --push
Options:
--private
: Make repository private. Use--public
for public.--source=.
: Use current directory as source.--remote=<remote>
: Set remote name (default:origin
).--push
: Push current commits.
Cloning a Repository #
You only run git clone
once, the first time you set up the repository.
Run:
git clone [email protected]:<user>/<repo>.git <local_folder>
This will:
- Create the
<local_folder>
directory - Pull all files into it
Pull latest changes:
cd <local_folder>
git pull
Reverting to a Specific Commit #
1. Using git revert
- Safely undo changes made in a specific commit by creating a new commit that reverses them.
- This method preserves history and is safe for shared/public branches.
Step 1: List Commits
Display history of commits:
git log --oneline
Output example:
e3a1f45 fix: broken image path
b2d3c7a add: user authentication
7f9e5a1 Initial commit
The left part (e.g. e3a1f45
) is the commit hash, used to identify a specific commit.
Step 2: Revert Commit
Run:
git revert <commit_hash>
Git opens your editor with a default commit message like:
Revert "Add user authentication"
- Edit or accept the message
- Save and close the editor to finalise the revert
git push origin master
Step 3: Push to Remote
Push the new revert commit to GitHub:
git push origin master
2. Using git reset
Only use
git reset
on branches that you alone are working on.Rewriting history on shared branches can cause conflicts and data loss for others.
- Use this method to permanently remove one or more commits from your local history.
- This is not safe on shared/public branches because it rewrites history.
Step 1: List Commits
Display history of commits:
git log --oneline
Output example:
e3a1f45 fix: broken image path
b2d3c7a add: user authentication
7f9e5a1 Initial commit
The left part (e.g. e3a1f45
) is the commit hash, used to identify a specific commit.
Step 2: Hard Reset to a Specific Commit
Run:
git reset --hard <commit_hash>
- This removes all commits after
<commit_hash>
- Your working directory and staging area will also be reset to that state
Step 3: Push to Remote
Push the new revert commit to GitHub:
git push origin master --force
Result: Remote history is overwritten with local state.
Deleting a Repository #
Step 1: Add Delete Repo Permission (optional)
Add user rights to delete repositry:
gh auth refresh -h github.com -s delete_repo
Step 2: Delete Repository
gh repo delete <user>/<repo> --yes
--yes
- Skip confirmation prompt and delete immediately.
Step 3: Verify Deletion
List all repositories:
gh repo list <user>
Press q
to exit.
Best Practices #
Following these best practices will help you use Git effectively, keep your history clean, and avoid common problems:
- Make small, focused commits with clear messages
Break your work into logical steps. Each commit should capture a single change, with a message that explains what changed and why. - Write commit messages that complete the sentence:
“If applied, this commit will...”. This approach ensures messages clearly describe the impact of the commit. Example: If applied, this commit willdocs: add installation instructions to readme
. - Pull frequently to stay up to date
Rungit pull
before you start working to ensure you have the latest changes. This reduces the risk of conflicts and rework. - Use branches for all new work
Create a separate branch for each feature, fix, or experiment. This keeps your main branch stable and makes reviews, testing, and rollbacks easier. - Check your status regularly
Usegit status
to monitor changes, staged files, and your current branch. This helps you stay in control and avoid mistakes. - Use
.gitignore
to exclude unnecessary files
Prevent build artefacts, system files, and secrets from being tracked. This keeps the repository clean and secure. - Use a
.gitmessage
template for consistent commits
Define a commit message template to encourage clear, structured, and meaningful commit messages. Especially useful for teams. - Clean up unused branches
Delete branches that have been merged or are no longer needed. This keeps your repository organised and easier to navigate. - Use public and private repositories appropriately on GitHub
- Use public repos for open source, demos, or portfolio work meant to be shared.
- Use private repos for proprietary, internal, or experimental work.
- Never publish sensitive data, such as API keys, passwords, or personal information.
- Audit visibility and access regularly to maintain proper control.
Troubleshooting #
Not a git repository #
Symptoms
Running any Git command results in the following error:
fatal: not a git repository (or any of the parent directories): .git
Cause
This error occurs when you run a Git command outside of a Git repository, meaning there is no .git
directory in the current or parent folders.
Solution
1. Check if you are inside a Git repository:
ls -a
Look for a .git
directory. If it's not there, you're not in a Git repo.
2. Navigate to the correct repository directory:
cd <path/to/repo>
3. If you haven’t initialised a repository yet
Initialise one in your current directory:
git init
4. If your repository was deleted or moved:
Re-clone the repository:
git clone <url>
Or restore .git
from a backup if available.
Modify Last Commit Message #
Problem
You need to change the message of your most recent commit.
Solution
1. Check for uncommitted changes:
git status
Ensure your working directory is clean.
2. Amend the last commit message:
git commit --amend
- This opens the commit message in your default editor
- Edit the message, save, and close the editor
3. Verify the updated commit message:
git log -1
4. If the commit is already pushed
You must force-push the amended commit:
git push --force
Force-pushing rewrites history and can disrupt collaborators.
Could not resolve HEAD #
Problem
Running the command:
git restore --staged <file>
returns the error:
fatal: could not resolve HEAD
Cause
This error occurs because your Git repository does not have any commits yet. The git restore --staged
command relies on comparing the staged changes against the latest commit (HEAD
). Without a commit, HEAD
is undefined, causing the failure.
Solution
1. If this is a new repository with no commits:
Use git reset
to unstage files instead:
git reset <file>
Or to unstage all files:
git reset
2. Alternatively, create an initial commit:
git commit -m "Initial commit"
After this, git restore --staged <file>
will work as expected.
Unable to add remote #
Symptoms
- Running a
gh repo create
command results in:
Unable to add remote "<remote>"
- The repository is created successfully on GitHub, but no remote is added or push fails.
Cause
A Git remote named <remote>
already exists in the local repository, causing a conflict when the GitHub CLI (gh
) tries to add a new remote with the same name.
Solution
Check existing remotes:
git remote -v
If <remote>
is listed, remove the conflicting remote:
git remote remove <remote>
Re-run the gh repo create
command:
gh repo create <user>/<repo> --private --source=. --remote=<remote> --push
Alternatively, use a different remote name if <remote>
is intentionally in use:
gh repo create <user>/<repo> --private --source=. --remote=<another_remote> --push
Next Steps #
Now that you’ve learned the essentials of Git, start applying your knowledge with real, practical use. Focus on the following two steps to build confidence and reinforce what you've learned.
1. Practise with Real Projects
- Start by creating a Git repository for a personal or hobby project
- Use branches to test new features or ideas
- Practise staging, committing, merging, and reverting changes
2. Explore GitHub
- Create a GitHub account (if you haven’t already)
- Push a project to a remote repository
- Learn to use pull requests, issues, and collaboration tools
- Set up GitHub Actions to automate tasks such as testing or deployment
As you keep practising, Git and GitHub will become second nature. The key is consistency and treating version control as an essential part of your development workflow.