DEV Community

Hanzla Baig
Hanzla Baig

Posted on

🌟 The Ultimate Git Reference: All Commands from Beginner to Advanced

Git is a distributed version control system (DVCS) originally created by Linus Torvalds. It lets multiple developers collaborate by tracking every change in your code history. Each developer has a full copy of the repository, enabling offline work and fast merges. Git is known for its speed, flexibility, and open-source community support. Every commit in Git records the author’s name and email, so you should configure these right after installing Git. Below is a comprehensive guide covering Git’s installation, configuration, and every major command, from basics to advanced tips.

Git’s architecture: The diagram above illustrates Git’s design: your working directory (red) holds your files, changes are staged into the index/cache (yellow), and committed into your local repository (green). You then synchronize with a remote repository (blue) on platforms like GitHub or GitLab. This flow (working → staging → commit → remote) is the heart of Git’s workflow.

🖥️ Installation & Setup

Before using Git, install it on your OS of choice. On Linux you can use the package manager: e.g. sudo apt install git-all (Debian/Ubuntu) or sudo dnf install git-all (Fedora/RHEL). On macOS, Git comes with Xcode command-line tools (running git --version prompts installation), or download the latest installer from git-scm.com. On Windows, download Git for Windows from the official site or use package managers like Chocolatey.

Once installed, configure your identity (one-time, globally):

git config --global user.name "Your Name"
git config --global user.email "[email protected]"
Enter fullscreen mode Exit fullscreen mode

This attaches your name/email to all future commits, and cannot be changed per commit later. You can also set defaults like your preferred text editor (core.editor) or enable color output (color.ui auto) with git config. For cross-platform line-ending consistency, set core.autocrlf: on macOS/Linux use git config --global core.autocrlf input, and on Windows use git config --global core.autocrlf true. This converts CRLF to LF on commit/push, avoiding messy diffs.

Additionally, create a .gitignore file in your repo root to exclude generated or sensitive files. You might also create useful aliases, e.g., git config --global alias.st status for shorthand. Many teams require signed commits or specific username/email formats—check your organization’s guidelines.

📦 Git Basics (Creating and Saving)

  • git initInitialize a repository. Run this in a project folder to start tracking it with Git:
  git init
Enter fullscreen mode Exit fullscreen mode

This creates a new .git directory. It’s the very first command in versioning a project.

  • git clone [url]Clone from remote. Copies an existing repository (and its history) to your local machine:
  git clone https://github.com/user/my-project.git
Enter fullscreen mode Exit fullscreen mode

This creates a new folder with the project, and a remote named origin pointing to that URL. Now you can work offline with a full copy.

  • git statusView changes. Shows which files are modified, staged, or untracked:
  git status
Enter fullscreen mode Exit fullscreen mode

Always run this before committing or switching branches to see your work-in-progress.

  • git add [file...]Stage changes. Moves changes from the working directory into the staging area:
  git add file1.txt
  git add .            # stage all changes in current folder
Enter fullscreen mode Exit fullscreen mode

Staging prepares a “snapshot” of your files for the next commit.

  • git commit -m "message"Record changes. Takes staged changes and saves them as a new commit in history:
  git commit -m "Fix bug in user login"
Enter fullscreen mode Exit fullscreen mode

Each commit should have a clear message. Commits are atomic units of work (one fix or feature per commit). After committing, your staging area is cleared until you git add again.

  • git logView history. Shows the commit history (latest on top) of the current branch:
  git log
Enter fullscreen mode Exit fullscreen mode

Combine with options (like --oneline, --graph, or date formats) to filter or format output. git log is often used with git blame or git bisect during troubleshooting (see below).

  • git diffInspect changes. Compare file differences between commits, branches, or the working directory. For example, git diff (with no args) shows unstaged changes, and git diff --staged shows staged but uncommitted changes. You can also do git diff HEAD~1 HEAD to see the difference between the last two commits. Example:
  git diff               # unstaged changes
  git diff --staged      # changes staged for commit
Enter fullscreen mode Exit fullscreen mode

The output highlights lines added (green) or removed (red). If you ever need to review what will be included in a commit, use git diff to make sure nothing surprising is happening.

  • git rm, git mv, git renameRemove or rename files.

    • git rm file.txt removes (and stages removal of) a tracked file.
    • git mv old new renames a file (or move it to a new location) in one step. These update both the working directory and staging area.

🔀 Branching & Merging

Git’s power shines with branches. A branch is a movable pointer to a series of commits, used to isolate development. Branches create independent lines of work. Use git branch [name] to list or create branches, and git checkout [branch] (or git switch [branch]) to switch context. For example:

git branch feature/login
git switch feature/login      # or `git checkout feature/login`
Enter fullscreen mode Exit fullscreen mode

Now you can work on the feature/login branch without affecting main. When ready, merge back into your main branch.

Branching diagram: The figure above shows how a feature branch (magenta) diverges from master and is later merged back. Note how the feature/signup branch’s commits (purple) merge into master without disturbing each other. Branching lets multiple features (or developers) progress in parallel.

  • git branchManage branches.

    • git branch lists all local branches, highlighting the current one.
    • git branch <name> creates a new branch off the current commit.
    • git branch -d <name> deletes a branch. This is your general-purpose branching tool.
  • git checkout / git switchChange branches or restore files. Traditionally, git checkout has two roles (switch branch, or restore files). Git 2.23+ introduced specialized commands:

    • git switch <branch> safely moves to an existing branch or git switch -c <new-branch> to create+switch.
    • git restore <file> reverts changes in the working directory (discard modifications). Example:
  git switch develop         # move to branch 'develop'
  git switch -c hotfix/1.0.1 # create and switch to new branch
Enter fullscreen mode Exit fullscreen mode

These make it clearer: git switch is for branch changes, git restore for undoing file edits. (Behind the scenes, these use the same mechanisms as git checkout.)

  • git merge <branch>Merge another branch into current. To combine changes from a branch into your active branch:
  git switch main
  git merge feature/login
Enter fullscreen mode Exit fullscreen mode

This finds the common ancestor and creates a new merge commit (unless it can fast-forward). Merge commits have two parents (one from each branch). Merging preserves the full history, making it clear when and why branches integrated. If conflicting changes exist, Git will pause for you to resolve them manually. After resolution, git add the fixed files and git commit to complete the merge.

  • Fast-Forward vs. No-FF: If main hasn’t moved since branching, git merge will simply move the main pointer forward (fast-forward). For record-keeping, use git merge --no-ff feature/login to always create a merge commit even when fast-forwarding.

  • git fetch & git pullSync with remote. First, add a remote with git remote add origin <url> (typically done during git clone). Then:

    • git fetch downloads new commits and branches from the remote, but doesn’t merge them.
    • git pull is essentially git fetch plus git merge (or --rebase) of the remote branch into your local one:
    git fetch origin
    git merge origin/main
    # or simply
    git pull origin main
    

Use pull to update your branch with upstream changes. Some teams prefer git pull --rebase to linearize history.

Multi-branch scenario: In this example, multiple developers (you, “Sarah”, “Max”) each create their own branches. Sarah’s and Max’s work (yellow and green, respectively) start from master and diverge. When each is ready, they merge back into master. Each merge can be done with git merge or via pull requests on platforms like GitHub/GitLab, enabling code review.

📚 Intermediate Workflows

  • Forking Workflow: On platforms like GitHub, you often fork a repository (create your own copy online), clone your fork locally, work there, and then open a Pull/Merge Request to upstream. git remote add upstream <original_repo> lets you pull changes from the original repo. Then use git fetch upstream and git merge upstream/main (or rebase) to stay up-to-date.

  • Gitflow & Branch Models: Large projects often follow structured workflows. Gitflow uses dedicated branches for develop, feature/*, release/*, hotfix/*. For example, create a feature branch off develop, then git merge into develop when done, and later release branches get merged into main. Alternatively, feature-branch workflow means each feature gets its own branch and is merged into main via pull request. Choose one strategy and stick with it, documenting it for your team.

  • Stashing – If you’re midway on some work but need to switch contexts, git stash temporarily shelves your uncommitted changes:

  git stash         # saves and reverts changes
  git switch other-branch
  # ... work on something else ...
  git switch -      # back to previous branch
  git stash pop     # re-apply stashed changes
Enter fullscreen mode Exit fullscreen mode

This is handy for preserving a clean working directory while you address urgent work.

🔧 Undoing Changes & History Editing

  • git resetUnstage or move HEAD. With no options, git reset <file> unstages changes (moves from index back to working directory). With flags:

    • --soft moves the HEAD pointer to a previous commit but leaves all changes staged.
    • --mixed (default) unstages changes but keeps them in working dir.
    • --hard resets everything (HEAD, index, working dir) to the specified commit. Use git reset with caution: it rewrites history and discards commits if they were not pushed.
  • git revertSafe rollback. Unlike reset, git revert <commit> creates a new commit that undoes the changes of the given commit. This is the recommended way to “undo” a public commit, as it preserves history. Example:

  git revert abc123    # creates a new commit that reverses commit abc123
Enter fullscreen mode Exit fullscreen mode
  • git cleanRemove untracked files. If you have new files you don’t want, git clean -f deletes them from the working directory. Useful for cleaning build artifacts. (Add -d to remove untracked directories, and use -n to preview).

  • git commit --amendEdit last commit. If you just committed but forgot something, use:

  git add missing_file
  git commit --amend
Enter fullscreen mode Exit fullscreen mode

This replaces the previous commit with a new one (including your new changes or updated message). Be very careful: amending rewrites history. Only amend commits not yet pushed (or be prepared to force-push and coordinate).

  • git rebaseMove or combine commits. Rebasing reapplies commits from one branch onto another, creating a linear history. For example, to incorporate upstream changes into your feature branch:
  git switch feature
  git fetch origin
  git rebase origin/main
Enter fullscreen mode Exit fullscreen mode

This moves your feature branch commits to start from the tip of main. Benefits: a clean, linear history (no merge commits) and easier git log bisecting. Golden Rule: never rebase public/shared branches (it rewrites history others may rely on).

Interactive rebase: git rebase -i HEAD~n lets you squash, reorder, or edit commits. This is powerful for cleaning up series of small commits before merging. For example, pick, squash, fixup commands in the rebase todo can merge multiple commits into one.

  • git cherry-pick <commit>Copy a commit. Applies a single commit from another branch onto your current branch. For instance, if main has a bugfix commit you need in develop:
  git switch develop
  git cherry-pick abc123
Enter fullscreen mode Exit fullscreen mode

This reapplies commit abc123 (from anywhere) as a new commit on develop.

  • git stash branch <branch> – Create a new branch and apply stash in one step:
  git stash branch new-feature
Enter fullscreen mode Exit fullscreen mode
  • git submodule – Include external repos. If your project depends on another Git repo, use submodules (though many prefer alternatives). For example:
  git submodule add https://github.com/lib/project.git libs/lib-project
Enter fullscreen mode Exit fullscreen mode

This creates a .gitmodules file tracking a specific commit of that repo. Submodules are fixed to a commit and do not auto-update. Use them when you need strict version control over an embedded dependency.

  • Other advanced commands: git bisect (binary search to find a bad commit), git reflog (recover lost commits by looking at reference logs), git blame (see who last modified each line), git cherry (find commits not merged), git filter-repo or git filter-branch (rewrite history globally, e.g., remove a password from all commits). Each of these has powerful use-cases:

    • git bisect automates a binary search through commit history to isolate the exact commit that introduced a bug.
    • git reflog shows all moves of HEAD, enabling you to recover "lost" commits (for example, after an accidental reset).
    • git blame annotates each line of a file with the last commit and author that changed it, great for tracking origin of code.
  • git tagTag a commit. Mark a specific commit, often for releases. Lightweight tags (git tag v1.0) or annotated tags (git tag -a v1.0 -m "Release 1.0"). You can push tags with git push origin --tags.

🤝 Collaboration & Team Workflows

Git shines in team settings, but good habits matter:

  • Commit small, atomic changes. Follow best practice: “make incremental, small changes” and keep commits atomic (one fix/feature per commit). This makes code review and rollback easier.

  • Descriptive commit messages. Write messages in imperative present tense (e.g., “Add user login validation” not “Added”) and clearly explain why a change was made. A good message helps teammates and your future self understand the context.

  • Branching strategy. Agree on a workflow: centralized (everyone commits to main directly), feature-branch (one branch per feature, then PR merge), GitFlow (with develop/release branches) or personal branches. Document it so everyone follows the same approach. For example, do you squash commits on merge, or keep full history? Set branch protection rules on the remote (require reviews, forbid force-push to main, etc.).

  • Code reviews and pull requests. Always get feedback via PRs/MRs before merging to main. Code reviews improve quality and share knowledge. Set up CI tests on PRs to catch issues early.

  • Regular syncing. Frequently git pull --rebase (or merge) to incorporate teammates’ changes into your branch. The more often you sync, the fewer conflicts accumulate. If working long-lived branches, consider rebasing often to keep history tidy.

  • Cross-platform tips: Windows users should be mindful of line endings and path length issues. We mentioned core.autocrlf above. Also, Unix permissions (executable bits) don’t always translate to Windows—use .gitattributes to manage differences. Git Bash or WSL on Windows mimics Unix-like behavior for commands.

  • Git Hooks: Teams often use Git hooks to enforce policies (e.g., pre-commit to run linters, pre-receive on server to enforce commit message format). Explore .git/hooks or tools like Husky to automate checks.

  • Git LFS: For large binary files (assets, media), use Git Large File Storage (LFS) so you don’t bloat the repo. It replaces big files with pointers.

  • Backup and Remote: Always push to a shared remote (GitHub/GitLab/Bitbucket). This acts as offsite backup (every clone is a backup copy). Enable branch protection or require signed commits if your org needs high security.

  • Custom Tools and GUIs: While Git CLI is powerful, many teams use GUIs. Examples:

    • GitHub Desktop (cross-platform, free) – basic commit/branch GUI.
    • Sourcetree (free, Atlassian) – visualizes branches and commits.
    • GitKraken, SmartGit, Tower – commercial clients with advanced features.
    • TortoiseGit – Windows Explorer integration.
    • Built-in IDE integrations (VSCode, IntelliJ, etc.) also provide visual diff/merge tools. These tools wrap underlying Git commands (so all CLI knowledge still applies), but offer graphical convenience.

🛠️ Debugging & Troubleshooting

  • Merge conflicts: When a merge or rebase stops at a conflict, Git marks the conflict in files. Edit the files to resolve (look for <<<<<<< markers), then git add the resolved files and git commit (or git rebase --continue). Use git merge --abort to undo a merge in progress, or git rebase --abort to cancel a rebase.

  • git bisect – to find a bad commit:

  git bisect start
  git bisect bad                  # current version has the bug
  git bisect good v1.2.3          # a known good older tag/commit
Enter fullscreen mode Exit fullscreen mode

Git will checkout a mid-point commit; test your code and then run git bisect good or git bisect bad. Repeat until Git pinpoints the exact commit that introduced the issue. This is invaluable for regression hunting.

  • Recovering lost commits: If you thought you lost work (e.g., after a bad reset), use git reflog to list where HEAD has been. You can often git reset back to a commit hash shown in reflog to recover. Think of reflog as undo history.

  • git blame – Find origin of code. Run git blame file.txt to see who last modified each line in a file. Useful to identify when/why a bug was introduced. Many hosting services (Bitbucket/GitHub) show blame info graphically in the UI.

  • Network issues: If git push is rejected due to conflicts or non-fast-forward, pull first or use --force-with-lease carefully if you know you must overwrite the remote (only on personal branches, never on shared main without coordination).

  • Authentication: Set up SSH keys or token-based auth for your remotes to avoid repeated password prompts. GitHub/GitLab provide specific instructions for SSH setup.

🔍 Tips & Best Practices

  • 🎯 Small, focused commits: Commit often with logical changes. Avoid “omnibus” commits that do many unrelated things. This makes review and reverts easier.

  • 📝 Use meaningful branch names: e.g. feature/login, bugfix/typo, hotfix/urgent-patch. Some teams prefix with JIRA issue IDs. Keep them concise and descriptive.

  • 🖋 Maintain a good commit history: Use interactive rebase (git rebase -i) to squash or reorder messy local commits before sharing. A clean history helps everyone. If merging via pull requests, you might squash and merge to keep main linear.

  • 🔐 Protect important branches: Configure your remote (GitHub/GitLab) to require pull request reviews, pass CI checks, and disallow force pushes on main/master and release branches. This prevents accidental overwrites.

  • ☑️ Review before pushing: Always git status and git diff to double-check what you’re about to commit or push. A quick git log --oneline --decorate --graph gives a visualization of where you stand.

  • Code reviews: As GitLab notes, “requesting feedback from others is an excellent way to ensure code quality”. Use pull request comments to discuss changes. Senior devs can mentor through reviews.

  • 🔄 Rebase vs. Merge policy: Decide with your team when to rebase. A common rule is: rebase before merging (for your private branch) to keep history tidy, but never rebase a public branch (like one others are using). Merges on shared branches keep everyone’s copy in sync.

  • 🛡️ Back up before big rewrites: If you are about to do something destructive (like git filter-branch, or a large rebase), make a backup of the repository folder (or a git bundle). It’s easy to lose work with powerful commands.

  • 🌐 Stay up-to-date with Git: New versions occasionally add helpful commands (git switch, git restore in 2.23+, git worktree to have multiple working directories from one repo, etc.). Check release notes or git-scm.com for new features.

  • 🤝 Communication: Always communicate with your team. If you must force-push a branch, alert others. If you encounter a tricky conflict, ask before just proceeding blindly. Good Git usage is as much about collaboration as it is about commands.

🌐 Cross-Platform & GUI Notes

  • Windows vs. macOS/Linux: Git commands are the same, but watch out for line endings (core.autocrlf). On Windows, path length can hit limits; Git for Windows provides Git Bash, a Unix-like terminal that smooths over many differences. On macOS/Linux, Git is native.

  • GUI clients: They wrap Git in visual form. Here are a few notable ones:

    • GitHub Desktop (Windows/macOS, free): Great for beginners, integrates GitHub features.
    • Sourcetree (Windows/macOS, free): Visual branch management for Bitbucket/GitHub.
    • GitKraken (cross-platform, free & paid tiers): Advanced UI, integrated issue tracking.
    • Tower (macOS/Windows, paid): Feature-rich professional GUI.
    • Many IDEs (VS Code, IntelliJ, etc.) have built-in or plugin Git integration, showing diffs and providing one-click commit/push. Choose one you like—just remember the underlying commands work the same way. Even with a GUI, know the CLI basics for troubleshooting.

🎉 Conclusion

Git is incredibly powerful and flexible. This guide has covered its core commands (init, clone, add, commit, status, log, diff, branch, checkout/switch, merge, pull, push), intermediate tools (rebase, stash, cherry-pick, tag, reset, revert, remote, submodule), and advanced techniques (bisect, reflog, blame, hooks). We’ve also touched on workflows, team collaboration tips, cross-platform considerations, and GUI alternatives.

Mastering Git takes practice. Always write clear commit messages, use branches to keep work isolated, and pull/merge frequently. Use code reviews to catch issues early. Back up your work with remotes and test merges on small changes first. And remember: if something goes wrong, commands like git reflog, git reset, and git revert can often recover you.

By following the best practices above, Git will streamline your development and collaboration. Happy coding! 🚀


Image description
AquaScript APIs
This website is created by me and my Best Friends Precious Kelvin & Madhurima Rawat. AquaScript Offers free APIs to The Developers

AquaScript | Free JSON APIs for Developers

Access high-quality, reliable JSON APIs for books, movies, quotes, jokes, and more. Easy to integrate, free to use, and constantly updated.

favicon aquascript.xyz


Top comments (3)

Collapse
 
dotallio profile image
Dotallio

Great writeup! Having commands like reflog and bisect spelled out here would've saved me hours in the past. What's the one 'advanced' Git command that's been a lifesaver for you?

Collapse
 
kaustubhtripathi profile image
Kaustubh Tripathi

Very detailed article. Nice one

Collapse
 
lehlohonolo_mashaya_24a21 profile image
Kwazi Lehlohonolo Mashaya

Fantastic.