· 10 min read

The Only Git Article You'd Ever Need - 3/4

Advanced Git

If you’ve actually made it till here, give yourself a pat on the back. You’re doing a pretty good job! Time to dive deeper into this git-ussy (not sorry for this one) and rip this baby apart.

Commit Hygiene: Professional Standards for Your Project History

Your commit history represents more than just a record of changes. It shows that you know your stuff. Easy to understand commits help teammates understand your reasoning, make debugging easier, and create a clear narrative of your project’s development.

How Often Should You Commit?

The answer is simple: after every logical change. Each commit should represent one complete, coherent modification to your codebase.

Rule of Thumb: If your commit message requires the word “and,” you’ve probably combined multiple logical changes. Each commit should be a single, atomic unit of work that serves a specific purpose.

This approach benefits everyone:

  • Debugging: Tools like git blame can pinpoint exactly when specific changes were introduced
  • Reverting: Rolling back small, focused changes is much safer than undoing large, complex commits
  • Code Review: Reviewers can understand each change individually rather than wrestling with massive, multi-faceted commits

Commit Message Conventions

Clear commit messages are essential professional practice. You’re creating a historical record that directly impacts your team’s ability to understand, debug, and maintain the codebase. Conventional Commits provides a standardized format that makes commit histories immediately understandable and actionable.

The Format:

<type>(<scope>): <subject>

[optional (but good-to-have) <body>]

[optional <footer>]
  • <type> (mandatory): A keyword for the nature of the change.

    • feat: A new feature (minor release if following SemVer).
    • fix: A bug fix (patch release if following SemVer).
    • docs: Documentation only changes.
    • style: Changes that don’t affect the meaning of the code (whitespace, formatting, missing semicolons, etc.).
    • refactor: A code change that neither fixes a bug nor adds a feature. Improves internal structure or readability.
    • perf: A code change that improves performance.
    • test: Adding missing tests or correcting existing tests.
    • chore: Changes to the build process or tools and libraries (e.g., updating dependencies, config files).
    • build: Changes that affect the build system or external dependencies (e.g., gulp, npm).
    • ci: Changes to CI configuration files and scripts (e.g., Travis, BrowserStack, yada yada).
  • <scope> (optional, but recommended): The part of the codebase affected by the change. Be as specific as possible but don’t go overboard.

    • Examples: auth, user-profile, navbar, api, DB, config, deps.
    • feat(auth): Add password reset functionality
    • fix(navbar): Correct overlap on mobile
    • chore(deps): Update react-router-dom to v6
  • <subject> (mandatory): Short description of the change.

    • Imperative Mood: “Add login page,” not “Added login page” or “Adds login page.” Think of it as a command to the codebase.
    • Capitalize the first letter.
    • Under 50 characters (for readability in git log and GitHub UI).
    • No period at the end.
  • <body> (optional): A longer description providing more context. Explain the why, not the how.

    • Why was this change necessary? What problem does it solve? What are the side effects?
    • Use bullet points for readability if necessary. Wrap lines at around 72 characters.
  • <footer>(s) (optional): Used for breaking changes, referencing issues, or other meta information.

    • BREAKING CHANGE: <description of change> (always uppercase for easy parsing).
    • Closes #69: Links to an issue on GitHub.

Example:

feat(auth): Add password reset functionality

This change introduces a new password reset flow for users.
Users can now request a password reset link via email, which
expires after 1 hour. This addresses issue #45.

- Implemented new API endpoint for reset requests.
- Added email template for reset links.
- Updated user schema to include reset token fields.

Closes #45

Bad Examples (and why they suck):

  • did some changes (Couldn’t get more useless than this)
  • Fixed bug and added feature (Violates “no ‘and’”, too generic)
  • Update (No type, no subject, just dread)
  • Added login page. (Period, not imperative)

Adopt this standard. Your team (and I) will love you. Your git log will be readable. And some tools can generate changelogs or determine version bumps.

Authentication: Secure Access to Remote Repositories

When you push code to GitHub, the platform needs to verify your identity to protect against unauthorized access to your repositories. Traditional password authentication for Git operations has been deprecated due to security concerns, replaced by more secure methods like Personal Access Tokens and SSH keys.

HTTPS + PATs (Personal Access Tokens)

Personal Access Tokens serve as somewhat secure replacements for traditional passwords in Git operations.

  • What it is: A PAT is a randomly generated string that functions as a cancellable credential for your GitHub. You generate PATs through GitHub and can configure specific permissions (scopes) for each token, like read-only access to public repositories or write access to specific private repositories. Tokens can also be given expiration dates.
  • The Good
    • Relatively easy to set up for a quick push, especially if you’re primarily using HTTPS.
    • You can revoke specific tokens without changing your main GitHub password.
    • Good for automated scripts or CI/CD pipelines where you need programmatic access.
  • The Bad:
    • It’s still a token you have to manage. You might store it in a password manager.
    • If someone gets their hands on your PAT, they can do whatever that token is authorized to do.

Read this to know how to set this up, if you want to. I am not going to explain it since PATs aren’t really preferred.

SSH (Secure Shell)

SSH authentication comes with better security and convenience out of the box compared to PATs. People say that the initial setup requires more effort, but to be honest I don’t see much difference. SSH and PAT are both easy to set up.

  • What it is: SSH relies on a pair of cryptographic keys:
    • Private Key: Stored securely on your local machine. Never share this. Ever. It’s your house key.
    • Public Key: You upload this to GitHub. It’s a unique lock on your GitHub account that only your private key can open. When you connect to GitHub, your machine uses your private key to prove its identity to GitHub, which verifies it against your public key. No passwords, no tokens to paste.
  • The Good:
    • Security: SSH provides better security than PATs because your private key never leaves your local machine.
    • Convenience: Once configured, authentication happens automatically without passwords or tokens.
    • Cryptographic Shit: Even if someone intercepts your public key, it’s useless without your corresponding private key.
  • The Bad:
    • Initial Setup: The process of generating keys, configuring the SSH agent, and adding keys to GitHub can be challenging for some people but like I said, it’s really not that difficult in my opinion.

Setup (you’ll need to look up details for your specific OS):

  1. Check for existing keys: ls -al ~/.ssh

  2. Generate a new SSH key pair:

    • ssh-keygen -t ed25519 -C "[email protected]"
    • Follow prompts, choose a passphrase if you want to.
    • This creates id_ed25519 (private) and id_ed25519.pub (public) in your ~/.ssh directory.
  3. Start the SSH agent and add your key:

    • eval "$(ssh-agent -s)"
    • ssh-add ~/.ssh/id_ed25519 (enter the passphrase).
  4. Add your public key to GitHub:

    • Copy the content of your public key: cat ~/.ssh/id_ed25519.pub
    • Go to github.com -> Settings -> SSH and GPG keys -> New SSH key, and paste the copied public key.
  5. Change your remote URL to SSH: If you previously used HTTPS, you need to update your local repo’s remote URL.

    git remote set-url origin [email protected]:your-username/your-repo-name.git
    

    Now, git push and git pull should work seamlessly without password prompts.

Documentation & Project Management

Knowing Git commands is useless if your project is an undocumented mess and your workflow is pure chaos. This is about making your project understandable and your work trackable.

The README.md

A README.md file is the absolute first thing anyone looks at when encountering your project. It’s not a suggestion; it’s a requirement. If your README is empty or provides no/minimal info, yeah…good luck in life 👍

What a good README.md must include

  • Project Title & Description: What is this thing? What does it do?
  • Purpose/Motivation: Why does this project exist? What was the goal? What does this solve?
  • Features: List of key functionalities.
  • Getting Started (Installation/Setup): This is important.
    • Prerequisites (Node.js, Python, Docker, Git, etc., with version requirements).
    • Step-by-step instructions on how to clone the repo, install dependencies, and run the project locally. Include exact commands.
    • git clone <url>
    • npm install or pip install -r requirements.txt or whatever
    • npm start, python app.py, etc.
    • Expected output/URL (e.g., “Open your browser to http://localhost:3000”).
  • Usage Examples: How do people actually use your application or library?
  • Contributing Guidelines (for open-source): How can others contribute? (e.g., “See CONTRIBUTING.md”)
  • License (optional): What license is the project under?
  • Contact/Credits: Who made this? How can they be reached?

Issues: Project’s Task List and Bug Tracker

Stop tracking bugs in your own mind in 2025 already.

  • What it is: An “Issue” (or “ticket” in other systems) on GitHub is a record of something that needs to be done.
    • A bug report is an Issue.
    • A feature request is an Issue.
    • A task for a refactor is an Issue.
    • A chore like “update dependencies” is an Issue.
  • Why use it:
    • Trackability: Every piece of work has a unique ID and history.
    • Prioritization: You can assign labels (bug, enhancement, critical), assignees, and milestones.
    • Discussion: Comments can be added to discuss the issue, share screenshots, or propose solutions.
    • Transparency: Everyone on the team knows what’s being worked on, by whom, and its status.
  • Best Practice:
    • Create an issue for every single task you work on.
    • When you create a feature branch, name it something like feat/123-add-login-page (where 123 is the issue number).
    • In your commit messages, reference the issue (Closes #123, Fixes #45, Refs #789). GitHub automatically links them.

Projects: Kanban Board

Issues are individual tasks. Projects organize those tasks into a visual workflow.

  • What it is: A Kanban board (columns like “To Do,” “In Progress,” “Done,” “Blocked”). You drag and drop issues between columns to represent their current status.
  • Why use it:
    • Progress Tracking: Understand what’s being worked on, what’s blocked, and what’s completed.
    • Resource Allocation: Easily see who’s working on what.
    • Sprint Management: Organize work into sprints or iterations.

Because you’re building software as part of a team (even if that team is just you and your future self). Showing some sanity in git means clean history, clear communication, and a well-managed workflow. Master these, and you’ll ascend.

Essential Professional Tools

.gitignore: Keeping Your Repository Clean

Not every file in your project directory belongs in version control. Build artifacts, dependency folders, environment files, and personal configuration shouldn’t be tracked by Git. The .gitignore file tells Git which files and folders to ignore completely.

Common .gitignore patterns:

# Dependencies
node_modules/
vendor/

# Build outputs
dist/
build/
*.exe
*.dll

# Environment files
.env
.env.local
config.local.json

# OS generated files
.DS_Store
Thumbs.db

# Editor files
.vscode/
.idea/
*.swp

# Logs
*.log
logs/

Why this matters: Committing generated files, dependencies, or sensitive configuration creates repository bloat. A well-crafted .gitignore keeps your repository focused on shit that actually matters.

Git Hooks: Automating Quality Control

Git hooks are scripts that run automatically when certain Git events occur. They’re powerful tools for enforcing code quality, running tests, and maintaining consistent practices across your team.

Common hooks:

  • pre-commit: Runs before each commit. Perfect for code formatting, linting, or running quick tests.
  • pre-push: Executes before pushing to remote. Ideal for running full test suites.
  • post-merge: Triggers after successful merges. Useful for dependency updates or cache clearing.

Example pre-commit hook (simplified):

#!/bin/sh
# Run linter before allowing commit
npm run lint
if [ $? -ne 0 ]; then
  echo "Linting failed. Fix issues before committing."
  exit 1
fi

Devs are humans (surprisingly), and they forget shit as well. Hooks ensure consistentcy. They can protect your code standards if and when the dev forgets to.

At this point, you have a solid understanding of Git that surpasses most developers who only know basic commands. You understand the underlying concepts, professional workflows, and can handle complex scenarios with confidence.

For those who want to go till the absolute end and cover every single thing, see you in the next part. For others, see you in some other article :)