- Introduction
- Getting Started with Git
- Basic Git Commands
- Git Configuration
- Understanding Git History
- Managing Remote Repositories
- Managing Files with .gitignore
- Staging Area Management
- Git History Manipulation
- Git Tagging
- 10.1 What are Git Tags?
- 10.2 Creating Tags
- 10.3 Managing Tags
- Troubleshooting Common Git Issues
- Advanced Topics
- Summary of Key Git Commands
This document serves as a comprehensive guide to Git, a powerful distributed version control system. It covers fundamental Git commands, configuration, history management, and advanced topics such as handling sensitive data and troubleshooting common issues. This guide is designed for developers of all experience levels, providing clear explanations and practical examples to enhance your understanding and proficiency with Git.
To begin working with Git, you can either initialize a new repository for a new project or clone an existing repository from a remote source.
Version control (like Git) is a system that tracks changes in code over time. It lets multiple developers collaborate safely by merging changes, and it keeps a history of everything done. You can go back to previous versions if something breaks. This is important because it helps manage code, avoid conflicts, and keep a record of all work.
When starting a new project that you wish to track with Git, you will typically initialize a new Git repository in your project directory. This command creates a new .git subdirectory, which contains all the necessary Git metadata for the repository.
git initAfter initialization, you might want to create a README.md file to describe your project and add it to your repository.
echo "# Your_Project_Name" >> README.md
git add README.md
git commit -m "first commit"To connect your local repository to a remote repository (e.g., on GitHub), you need to add a remote origin. Replace your-remote-repository-url with the actual URL of your remote repository.
git remote add origin your-remote-repository-urlFinally, push your initial commit to the remote repository. The -u flag sets the upstream branch, so you can simply use git push in the future.
git push -u origin mainIf you are joining an existing project or want to work on a project hosted remotely, you can clone the repository. Cloning downloads a complete copy of the repository, including all files, branches, and commit history, to your local machine.
There are two primary methods for cloning: HTTPS and SSH.
Cloning with HTTPS:
This method is generally simpler for read-only access and does not require SSH key setup. However, you will need to provide your username and password (or a personal access token) for write operations.
git clone https://github.com/your-username/your-repo.gitCloning with SSH:
SSH provides a more secure way to interact with remote repositories, especially for frequent write operations, as it uses SSH keys for authentication. This requires prior setup of SSH keys on your system and adding them to your Git hosting service (e.g., GitHub).
git clone git@github.com:your-username/your-repo.gitAfter cloning, you can verify the remote origin to ensure it's correctly set up:
git remote -vCloning a Specific Branch:
Sometimes, you might want to clone a specific branch of a repository directly, rather than the default branch (usually main or master). This is particularly useful for projects that maintain different branches for active development and stable releases.
To clone a specific branch (e.g., stable):
git clone -b stable https://github.com/your-username/your-repo.gitThe -b (or --branch) flag tells Git which branch to check out immediately after cloning. This avoids the need to manually switch branches after the initial clone.
Understanding and utilizing basic Git commands is crucial for effective version control. These commands allow you to manage your project's history, collaborate with others, and maintain a clean and organized codebase.
The git status command provides a summary of the current state of your working directory and the staging area. It shows which changes have been staged, which haven't, and which files aren't being tracked by Git.
git statusBranches are fundamental to Git, allowing you to work on different features or bug fixes in isolation from the main codebase. This section covers essential commands for managing branches.
To list all local branches:
git branchTo list all remote branches:
git branch -rTo list all local and remote branches:
git branch -aTo switch to the last branch you were on:
git checkout -To switch to a specific existing branch:
git checkout your-branch-nameTo create a new branch and immediately switch to it:
git checkout -b new-branch-nameIf a branch exists on the remote but not locally, you can create and switch to it based on the remote branch:
git checkout -b your-branch-name origin/your-branch-nameTo find the currently active Git branch:
git branch --show-current
# Alternatively:
git rev-parse --abbrev-ref HEADAfter making changes to your files, you need to stage them and then commit them to your repository's history.
To stage all changes in the current directory (including new files, modifications, and deletions):
git add .To stage specific files:
git add file1.js file2.pyTo commit staged changes with a descriptive message:
git commit -m "Your descriptive commit message"To stage all modified files and commit in one command (does not include new untracked files):
git commit -am "Your commit message"Remote repositories are versions of your project that are hosted on the internet or network. They are essential for collaboration and backing up your work.
To verify the remote repositories configured for your project:
git remote -vTo fetch the latest changes from the remote repository and then switch to a specific branch (useful for updating your local branch with remote changes):
git fetch && git checkout your-branch-nameTo push your local commits to the remote repository. The -u flag sets the upstream branch, which is useful for subsequent pushes.
git push -u origin main
# Or for a new remote and branch:
git push new_remote_name branch_nameFor pushing to a specific GitHub repository using a Personal Access Token (PAT) for authentication (replace placeholders):
git push https://YOUR_GITHUB_USERNAME:YOUR_PERSONAL_ACCESS_TOKEN@github.com/your-username/your-repo.gitTo pull changes from a specific remote and branch:
git pull origin mainTo fetch all branches and their respective commits from the remote repository:
git fetch originGit allows extensive configuration to tailor its behavior to your preferences and project needs. These configurations can be set at different levels: system, global (user), and local (repository).
To view your Git configuration settings, you can use the git config command with various flags.
To display all Git configuration settings for your user account on the current system:
git config --listTo show only global settings (those applied to all your repositories):
git config --global --listTo show only local repository settings (those specific to the current repository):
git config --local --listIt is essential to configure your Git username and email address, as this information is embedded in every commit you make. This helps identify who made which changes.
To change your global Git username:
git config --global user.name "Your Name"To change your global Git email address:
git config --global user.email "your-email@example.com"Line ending inconsistencies between different operating systems (Windows uses CRLF, macOS/Linux use LF) can cause issues in collaborative projects. Git provides the core.autocrlf setting to manage this automatically.
To configure Git to convert CRLF to LF on commit (for macOS or Linux users), ensuring Unix-style line endings in the repository, but leaving line endings unchanged on checkout:
git config --global core.autocrlf inputTo configure Git to convert LF to CRLF on checkout and CRLF to LF on commit (for Windows users):
git config --global core.autocrlf trueTo disable automatic conversion and leave line endings unchanged:
git config --global core.autocrlf falseFor most macOS and Linux users, setting core.autocrlf to input is recommended. This helps maintain consistent line endings across different development environments.
Git maintains a detailed history of all changes made to your repository, allowing you to track, review, and revert modifications. Understanding how to navigate and interpret this history is crucial for effective version control.
The git log command is your primary tool for exploring the commit history. It displays a list of commits in reverse chronological order, showing the commit hash, author, date, and commit message.
To view the full commit history with detailed information:
git logFor a more compact view, displaying each commit on a single line with an abbreviated commit hash and message:
git log --onelineTo limit the display to a specific number of commits (e.g., last 10 commits):
git log --oneline -10To visualize branches and their commit history graphically:
git log --graph --oneline --allTo see commits along with the patches or changes introduced by each commit:
git log -pTo see commits by a specific author:
git log --author="Your Author Name"To see commits within a specific date range:
git log --since="YYYY-MM-DD" --until="YYYY-MM-DD"To list all the files modified or added in a specific commit (replace commit-hash with the actual commit hash):
git diff-tree --no-commit-id --name-only -r commit-hashTo view recent Git operations (useful for finding lost commits):
git reflogSometimes you might need to modify the message of your most recent commit. The git commit --amend command allows you to do this.
To change the most recent commit message:
git commit --amend -m "Your new commit message"This command replaces the last commit with a new one that includes the previous commit's contents and any newly staged changes. If you have already staged new changes with git add ., they will be included in the amended commit.
Important Consideration: If the commit has already been pushed to a remote repository, amending it will create a new commit that diverges from the remote history. You will need to force push to update the remote:
git push --force-with-lease origin mainIf force-with-lease fails due to stale reference:
# Fetch latest remote references
git fetch origin
# Then force push
git push --force-with-lease origin mainIf you amend a commit and then decide you want to split it into two separate commits, you can do so by resetting the last commit and then re-committing your changes.
- Reset the last commit but keep changes staged:
git reset --soft HEAD~1This command moves the HEAD pointer back one commit, but keeps the changes from that commit in your staging area.
- Make two new commits:
Now your changes will be staged again. You can selectively commit them.
git commit -m "First part of the commit message"If some changes still remain staged after the first commit, unstage them:
git resetThen, selectively add the remaining changes and commit them:
git add . # or specific files
git commit -m "Second part of the commit message"This process allows you to refine your commit history by breaking down a single amended commit into more granular, logically separated commits.
Remote repositories are essential for collaboration and backup. This section covers how to manage and interact with remote repositories effectively.
If you need to change the remote URL after cloning, you can use the set-url command. This is useful if the repository's remote URL changes or if you initially cloned using HTTPS and now wish to switch to SSH, or vice-versa.
To update an existing remote URL:
git remote set-url origin your-new-remote-repository-urlTo completely remove and re-add a remote:
# Remove the old remote
git remote remove origin
# Add the new remote
git remote add origin https://github.com/new-username/new-repo.gitExample: Switching from one repository to another:
If you're working on a forked repository and need to switch to a different one:
# Update remote URL to point to new repository
git remote set-url origin https://github.com/studiointeriorm/StudioM.git
# Verify the change
git remote -v
# Fetch from new remote
git fetch originIf a remote repository is accidentally deleted and you have a local copy with all commits intact, you can restore it to a newly created repository.
Steps to restore:
- Verify your local repository is intact:
# Check your commit history is still there
git log --oneline -10
# Check current remote
git remote -v- Update the remote URL to point to the new repository:
git remote set-url origin https://github.com/your-username/new-repo.git- Push everything including all commits:
# Push with full history
git push -u origin main --force
# If you have multiple branches
git push --all origin --force
git push --tags origin --forceThis restores your entire project with complete commit history to the new repository.
Force pushing overwrites the remote branch with your local version. Use with extreme caution as it can delete other people's work.
Safer option - force push with lease:
git push --force-with-lease origin mainThis will fail if someone else has pushed to the branch since your last fetch, protecting against accidentally overwriting others' work.
Regular force push (use only when absolutely necessary):
git push --force origin mainUnderstanding the consequences:
When you force push, you completely replace the remote branch history with your local history. Any commits that exist on the remote but not locally will be permanently deleted. Always:
- Communicate with your team before force pushing
- Use
--force-with-leaseinstead of--forcewhen possible - Consider if there's a safer alternative (like reverting commits)
Effective use of .gitignore is crucial for maintaining a clean and manageable Git repository. This file tells Git which files or folders to intentionally ignore, preventing them from being tracked or included in commits.
A .gitignore file is a plain text file where each line contains a pattern for files or directories that Git should ignore. This is particularly useful for excluding temporary files, build artifacts, dependency directories (like node_modules), environment-specific configuration files, and operating system-generated files (like .DS_Store). By ignoring these files, you ensure that your repository only contains relevant source code and project assets, reducing repository size and avoiding unnecessary conflicts.
To set up a .gitignore file, you typically create it in the root directory of your Git repository. Each line in the file specifies a pattern for files or directories to ignore.
- Create the
.gitignorefile:
touch .gitignore- Add patterns to the file. Below is a suggested
.gitignoretemplate for projects that might involve both Node.js and Python components, along with common system and log files. You should adapt this to your specific project needs.
# Node.js specific ignores
node_modules/
npm-debug.log
# Optional: npm lock file if you prefer to not track it
package-lock.json
# Python specific ignores
__pycache__/
*.py[cod]
*.pyo
*.pyc
# Environment files
.env
.venv/
env/
venv/
# IDE specific files
.idea/
.vscode/
*.swp
*.swo
# Build directories
build/
dist/
*.egg-info/
# System Files (macOS, Windows)
.DS_Store
**/.DS_Store
Thumbs.db
# Log files
*.log
nohup.out
- Save and commit the
.gitignorefile:
After adding your desired patterns, save the file and commit it to your repository. This ensures that all collaborators will use the same ignore rules.
git add .gitignore
git commit -m "Add .gitignore"GitHub maintains extensive .gitignore templates for various programming languages and frameworks at https://github.com/github/gitignore.
A common scenario is that you might have mistakenly added and committed files (e.g., node_modules/, .DS_Store, .env) before setting up your .gitignore file. In such cases, Git will continue to track these files even after you add them to .gitignore.
To remove these files from Git's tracking (but keep them locally in your working directory), you need to use the git rm --cached command.
To untrack specific files or directories:
# Untrack a single file
git rm --cached .DS_Store
# Untrack a directory recursively
git rm -r --cached node_modules
# Untrack multiple items
git rm --cached .env
git rm -r --cached build/
git rm -r --cached .gradle/
git rm -r --cached .idea/
# Commit the changes
git commit -m "Remove unwanted tracked files and apply .gitignore"
git pushTo untrack all ignored files at once:
# Untrack everything
git rm -r --cached .
# Re-add only files that should be tracked
git add .
# Commit
git commit -m "Clean up unwanted tracked files using .gitignore"This sequence first untracks everything in your repository, then re-adds only the files that are not matched by any pattern in your .gitignore file.
Important: Adding a file to .gitignore ONLY prevents untracked files from being added. It does NOT stop tracking files that are already tracked by Git.
The Issue:
If a.txt is already tracked by Git, adding it to .gitignore will NOT prevent future changes from being committed. The file will continue to be tracked and any modifications will still show up in git status and be included in commits.
The Solution - Remove from Tracking:
# Add to .gitignore first
echo "a.txt" >> .gitignore
# Remove from Git tracking but keep local file
git rm --cached a.txt
# Commit the changes
git add .gitignore
git commit -m "Stop tracking a.txt and update .gitignore"
git pushWhat this does:
a.txtwill be deleted from the GitHub repository- The file remains in your local directory
- Future changes to
a.txtwill be ignored by Git
Note: There is no way to keep a file in the repository while preventing future updates to it. You must choose between:
- Keep file in repo + accept future updates
- Remove file from repo + ignore future changes
One common mistake is accidentally removing the .gitignore file from Git tracking. If you run git rm -r --cached .gitignore, the file will remain on your disk but Git will no longer track it.
To fix this, simply re-add the .gitignore file to Git:
git add .gitignore
git commit -m "Re-add .gitignore"Adhering to these best practices will help you maintain a clean and efficient Git repository:
- Create
.gitignoreearly: Always create and configure your.gitignorefile at the very beginning of your project. This prevents unwanted files from ever being tracked. - Never commit sensitive or unnecessary files: Ensure that directories like
node_modules,.envfiles (containing sensitive environment variables), and OS-specific junk files are always ignored. - Use
git rm --cached: If files are accidentally committed, usegit rm --cachedto stop tracking them without deleting them locally. - Leverage GitHub's
.gitignoretemplates: Utilize the official.gitignoretemplates provided by GitHub for project-specific setups.
Understanding how to manage the staging area is crucial for controlling what gets included in your commits.
If you've staged files but want to unstage them before committing, use git restore --staged.
To unstage specific files:
git restore --staged filename.txtTo unstage multiple files:
git restore --staged file1.js file2.py file3.cssTo unstage entire directories:
git restore --staged build/ .gradle/ .idea/To unstage all staged files:
git restore --staged .When working in subdirectories, files in parent directories won't be staged by git add . because . refers to the current directory.
Problem scenario:
# You're in android/ subdirectory
cd android/
git add .
git status
# Shows: modified: ../package.json (not staged)Solutions:
Option 1: Navigate to project root (recommended):
# Go to parent directory
cd ..
# Now stage all changes
git add .
git commit -m "Your message"Option 2: Stage from current location using parent path:
# Stage specific parent directory files
git add ../package.json ../src/
# Or stage all changes from parent
git add ..If you've staged multiple files but want to remove some specific ones from the staging area:
# Check what's staged
git status
# Remove specific files from staging
git restore --staged gpg-wrapper.sh gradle.properties
# Verify
git statusGit provides powerful tools for manipulating commit history. Use these carefully, especially on shared branches.
Resetting allows you to move your branch pointer to a different commit, optionally keeping or discarding changes.
To reset to a specific commit and discard all changes after it:
# Reset to commit hash (e.g., 547a7c7)
git reset --hard 547a7c7
# Force push to update remote
git push --force-with-lease origin mainTo reset but keep changes staged:
git reset --soft HEAD~1To reset but keep changes unstaged:
git reset HEAD~1Creating a backup before resetting:
# Create backup branch first
git branch backup-before-reset
# Then reset
git reset --hard 547a7c7
# Force push
git push --force-with-lease origin mainInteractive rebase allows you to modify, reorder, squash, or remove commits in your history.
To start interactive rebase:
# Rebase from the beginning of the repository
git rebase -i --root
# Rebase last N commits
git rebase -i HEAD~5
# Rebase from a specific commit
git rebase -i commit-hashIn the interactive rebase editor:
- pick - Use commit as-is
- drop - Remove commit entirely
- reword - Change commit message
- edit - Stop for amending
- squash - Combine with previous commit
- fixup - Like squash but discard commit message
Editor navigation (Vim):
- Press
ito enter INSERT mode - Edit the commands (change "pick" to "drop", etc.)
- Press
Escto exit INSERT mode - Type
:wqand pressEnterto save and quit
To remove specific commits (e.g., those containing sensitive data) from Git history:
Method 1: Interactive Rebase
# Start interactive rebase
git rebase -i --root
# In the editor, change "pick" to "drop" for commits to remove
# Example:
# drop 0697f23 first commit
# drop 04ea732 temp
# pick c558987 gradle build issue fixed
# Save and exit
# Then force push
git push --force-with-lease origin mainMethod 2: Using git revert (safer for shared branches)
Instead of removing commits, create new commits that undo the changes:
# Revert a range of commits
git revert --no-edit commit-hash..HEAD
# Or revert specific commits
git revert --no-edit commit-hash1
git revert --no-edit commit-hash2
# Push normally (no force needed)
git push origin mainTo undo a specific commit without removing it from history:
git revert commit-hashTo create a new commit with a specific old commit's content:
# Checkout files from an old commit
git checkout commit-hash -- .
# Commit as new state
git commit -m "Revert to working state from commit-hash"
git push origin mainTo jump to a specific commit and make it the new HEAD:
# Option 1: Create new commit with old state
git checkout f4bde0e -- .
git commit -m "Revert to working state from f4bde0e"
git push origin main
# Option 2: Reset and force push (rewrites history)
git reset --hard f4bde0e
git push --force-with-lease origin mainTags are references to specific points in Git history, commonly used for marking release versions.
Git tags are used to mark specific commits as important, typically for:
- Version Releases: Mark release points (v1.0.0, v2.1.5, etc.)
- GitHub Releases: Tags appear in the "Releases" section on GitHub
- Reference Points: Easy way to checkout specific versions later
Create an annotated tag (recommended):
git tag -a v1.0.0 -m "Initial release of PVM for macOS"Create a lightweight tag:
git tag v1.0.0Push a specific tag to remote:
git push origin v1.0.0Push all tags to remote:
git push origin --tagsList all tags:
git tagView tag details:
git show v1.0.0Delete a local tag:
git tag -d v1.0.0Delete a remote tag:
git push origin --delete v1.0.0Checkout a specific tag:
git checkout v1.0.0Example versioning workflow:
# First stable release
git tag -a v1.0.0 -m "First stable release"
git push origin v1.0.0
# Bug fix release
git tag -a v1.0.1 -m "Bug fixes for login issue"
git push origin v1.0.1
# Major update
git tag -a v2.0.0 -m "Complete UI redesign"
git push origin v2.0.0Even with a good understanding of Git, you might encounter common issues. This section provides solutions and explanations for frequently faced problems.
Error: Updates were rejected because the remote contains work that you do not have locally
This means the remote repository has commits that are not present in your local branch.
Solution 1: Merge Remote Changes (Recommended)
# Set upstream branch
git branch --set-upstream-to=origin/main main
# Pull and merge remote changes
git pull origin main --allow-unrelated-histories
# Push your changes
git push origin mainSolution 2: Force Push (
This will delete everything in the remote and replace it with your local version:
git push origin main --forceIf your local and remote branches have diverged, Git needs to know how to combine them.
Fix Option 1: Merge (Safe and Common)
git config pull.rebase false
git pullFix Option 2: Rebase (Cleaner History)
git config pull.rebase true
git pull --rebaseFix Option 3: One-time Override
# Merge for this pull only
git pull --no-rebase
# Rebase for this pull only
git pull --rebase
# Fast-forward only
git pull --ff-onlySet as Global Default:
# Merge (recommended for simplicity)
git config --global pull.rebase false
# Rebase (cleaner history)
git config --global pull.rebase true
# Fast-forward only
git config --global pull.ff onlyProblem: File doesn't appear after git add, git commit, and git push.
Common Causes:
- Incorrect file creation - Using
mkdirinstead oftouch - File ignored by .gitignore - A rule is blocking it
Step-by-Step Fix:
Step 1: Create the file correctly
# Create directory structure
mkdir -p .github/workflows
# Create the file (not directory)
touch .github/workflows/deploy.yml
# Add initial content
echo "# GitHub Actions workflow" > .github/workflows/deploy.ymlStep 2: Check which .gitignore rule is blocking it
git check-ignore -v .github/workflows/deploy.ymlStep 3: Fix the .gitignore rules
Option A - Refine the rule:
# Before (too broad):
.github/
# After (more specific):
.github/*
!.github/workflows/
!.github/workflows/deploy.yml
Option B - Force add the file:
git add -f .github/workflows/deploy.yml
git commit -m "Add GitHub Actions deploy workflow"
git pushStep 4: Verify the file was added
git status
git log --name-statusError: Permission denied (publickey) or no such identity: /Users/username/.ssh/id_ed25519
Solution 1: Use HTTPS Instead (Simpler)
git remote set-url origin https://github.com/your-username/your-repo.gitSolution 2: Fix SSH Key Setup
- Check for existing keys:
ls -la ~/.ssh/- Generate new SSH key:
ssh-keygen -t ed25519 -C "your-email@example.com"- Add key to SSH agent:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519- Add SSH key to GitHub:
# Copy public key
cat ~/.ssh/id_ed25519.pub
# Go to GitHub → Settings → SSH and GPG keys → New SSH key
# Paste the key- Test connection:
ssh -T git@github.comProblem: .DS_Store files (macOS system files) keep appearing in Git.
Solution:
Remove all .DS_Store files from staging:
git restore --staged **/.DS_StoreDelete actual .DS_Store files:
find . -name ".DS_Store" -type f -deleteRemove from Git tracking:
# Remove from Git but keep local
git rm --cached .DS_Store
# Or force remove if Git complains
git rm -f --cached .DS_StorePrevent future tracking:
# Add to .gitignore
echo ".DS_Store" >> .gitignore
echo "**/.DS_Store" >> .gitignore
# Commit changes
git add .gitignore
git commit -m "Remove .DS_Store files and update .gitignore"
git pushProblem: IDE configuration folders (.idea/) or build directories (build/, dist/) are being tracked.
Solution:
Remove from staging:
git restore --staged build/ .gradle/ .idea/Remove from Git tracking:
# For directories, use -r flag
git rm -r --cached .idea/
git rm -r --cached build/
git rm -r --cached dist/
# Add to .gitignore
echo ".idea/" >> .gitignore
echo "build/" >> .gitignore
echo "dist/" >> .gitignore
# Commit
git add .gitignore
git commit -m "Remove IDE and build files from tracking"
git pushIf Git complains about non-existent paths:
The directory might not be tracked. Just add it to .gitignore:
echo "dist/" >> .gitignore
git add .gitignore
git commit -m "Add dist/ to .gitignore"Problem: Git refuses to remove a staged file with error about "staged content different from both file and HEAD."
Solution:
Option 1: Unstage first, then remove (recommended):
# Unstage the file
git restore --staged .DS_Store
# Remove from tracking
git rm --cached .DS_Store
# Delete actual file
rm .DS_StoreOption 2: Force removal:
# Force remove (also deletes file)
git rm -f .DS_StoreUndo last commit but keep changes:
git reset --soft HEAD~1Undo last commit and discard changes:
git reset --hard HEAD~1Undo a git rm --cached operation:
# If not committed yet
git add filename.txt
# If already committed
git reset --soft HEAD~1
git add filename.txtUndo force push / rebase disaster:
# View recent operations
git reflog
# Reset to before the operation (e.g., HEAD@{1})
git reset --hard HEAD@{1}
# Force push to restore
git push --force-with-lease origin mainUndo changes made by git revert:
# Find the commit hash before the revert in reflog
git reflog
# Reset to that commit
git reset --hard commit-hash-before-revert
# Force push
git push --force-with-lease origin mainThis section delves into more advanced Git topics for power users.
If sensitive credentials, API keys, or other confidential information are accidentally committed, you need to rewrite Git history to truly remove them.
Using git-filter-repo:
- Install git-filter-repo:
pip install git-filter-repo- Remove sensitive file from all commits:
git filter-repo --path path/to/sensitive-file.txt --invert-paths --force- Force push cleaned history:
git push --force-with-lease origin mainAlternative: Using BFG Repo-Cleaner
BFG Repo-Cleaner is another powerful tool for cleaning repositories. Refer to its official documentation for usage.
SSH keys provide secure authentication with GitHub without exposing passwords.
Complete SSH Setup:
- Check for existing keys:
ls -al ~/.ssh- Generate new SSH key:
ssh-keygen -t ed25519 -C "your-email@example.com"Or for older systems:
ssh-keygen -t rsa -b 4096 -C "your-email@example.com"- Start SSH agent and add key:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519- Copy public key:
cat ~/.ssh/id_ed25519.pub-
Add to GitHub:
- Go to GitHub → Settings → SSH and GPG keys → New SSH key
- Paste the public key
- Give it a descriptive title
-
Test connection:
ssh -T git@github.comCreating custom aliases and functions can significantly speed up your daily Git workflow by combining multiple frequently-used commands into a single shortcut.
If you frequently run the same sequence of commands before committing (checking branch, repository URL, staging files, and viewing status), you can create a custom shell function to automate this workflow.
For macOS/Linux (zsh or bash):
- Open your shell configuration file:
# For zsh (default on macOS)
nano ~/.zshrc
# For bash
nano ~/.bashrc- Add the following function:
ggg() {
echo "Branch: $(git branch --show-current)"
echo "Repo: $(git remote get-url origin)"
git add .
git status
if [ -n "$*" ]; then
git commit -m"$*"
fi
}- Save and reload your shell:
# For zsh
source ~/.zshrc
# For bash
source ~/.bashrcUsage:
# Run pre-commit checks only (shows branch, repo, stages files, displays status)
ggg
# Run pre-commit checks AND commit with message
ggg Initial commit
ggg Fixed login bug
ggg Added user authentication featureWhat this function does:
- Displays current branch name
- Shows remote repository URL
- Stages all changes with
git add . - Shows repository status
- If you provide a message, commits with that message
- If no message is provided, stops after showing status
Customization:
You can modify this function to fit your specific workflow:
# Example: Add automatic push after commit
ggg() {
echo "Branch: $(git branch --show-current)"
echo "Repo: $(git remote get-url origin)"
git add .
git status
if [ -n "$*" ]; then
git commit -m"$*"
git push
fi
}
# Example: Add confirmation before staging
ggg() {
echo "Branch: $(git branch --show-current)"
echo "Repo: $(git remote get-url origin)"
read -p "Stage all changes? (y/n): " confirm
if [ "$confirm" = "y" ]; then
git add .
git status
if [ -n "$*" ]; then
git commit -m"$*"
fi
fi
}| Command | Description | Example |
|---|---|---|
git init |
Initialize new repository | git init |
git clone URL |
Clone existing repository | git clone https://github.com/user/repo.git |
git status |
Show repository status | git status |
git add . |
Stage all changes | git add . |
git add file |
Stage specific file | git add README.md |
git commit -m "msg" |
Commit staged changes | git commit -m "Add feature" |
git commit --amend |
Modify last commit | git commit --amend -m "New message" |
git push |
Push to remote | git push origin main |
git push --force-with-lease |
Safe force push | git push --force-with-lease origin main |
git pull |
Pull from remote | git pull origin main |
git fetch |
Fetch remote changes | git fetch origin |
git branch |
List branches | git branch |
git branch -r |
List remote branches | git branch -r |
git checkout branch |
Switch branch | git checkout develop |
git checkout -b branch |
Create and switch branch | git checkout -b feature/new |
git merge branch |
Merge branch | git merge feature/new |
git log |
View commit history | git log --oneline -10 |
git reflog |
View reference log | git reflog |
git reset --soft HEAD~1 |
Undo commit keep changes | git reset --soft HEAD~1 |
git reset --hard commit |
Reset to commit | git reset --hard abc123 |
git revert commit |
Revert commit | git revert abc123 |
git rebase -i --root |
Interactive rebase | git rebase -i --root |
git restore --staged file |
Unstage file | git restore --staged app.js |
git rm --cached file |
Untrack file | git rm --cached .env |
git rm -r --cached dir/ |
Untrack directory | git rm -r --cached node_modules/ |
git remote -v |
List remotes | git remote -v |
git remote set-url origin URL |
Change remote URL | git remote set-url origin https://... |
git tag -a v1.0.0 -m "msg" |
Create annotated tag | git tag -a v1.0.0 -m "Release" |
git push origin v1.0.0 |
Push tag | git push origin v1.0.0 |
git check-ignore -v file |
Check ignore rule | git check-ignore -v app.log |
git config --global user.name |
Set username | git config --global user.name "John" |
git config --global user.email |
Set email | git config --global user.email "a@b.com" |
End of Documentation
For more information, visit the official Git documentation at https://git-scm.com/doc.