KAHIBARO
Discord Login Register

3.7. Git

Why Git Matters for Backend Developers

Git is the standard tool for tracking changes in code. Almost every backend job expects you to know it. You will use Git to:

In this chapter you will focus on what makes Git useful in your daily backend work, not on every possible command.

What Git Actually Tracks

Git is a version control system. It keeps a history of:

Git does not store a copy of the entire project for each version. Instead, it stores a series of snapshots plus differences between them.

Imagine a project folder like this:

text
my-api/
  app.py
  models.py
  requirements.txt
  README.md

When you start using Git, it begins to track versions of these files. Every time you commit, you create a new snapshot of the files that changed.

Local vs Remote Repositories

You will often hear about:

You can work entirely with a local repository, but for collaboration and backup you almost always push your changes to a remote.

A typical backend workflow:

  1. Clone a remote repository to create a local copy.
  2. Work locally, changing files and committing.
  3. Push your commits back to the remote.
  4. Your teammates pull those commits into their own local copies.

Basic Git Concepts

Here are the most important concepts you will use daily.

ConceptWhat it isSimple analogy
Repository (repo)A project folder tracked by Git, with its full historyA library with all editions of a book
CommitA snapshot of your changes with a messageA saved game checkpoint
BranchA line of development, separate from othersA different storyline in your game
Working treeYour current files on diskThe page you are currently editing
Staging areaA temporary area where you prepare changes for a commitA basket of pages you are about to save
RemoteA copy of the repo on another computer or serverA backup library in another city

Important rule:
Never commit secrets such as passwords, API keys, private keys, or database URLs to Git.

Creating a New Git Repository Locally

You usually start tracking an existing project with Git like this:

bash
cd my-api
git init

This creates a hidden .git folder inside my-api. That folder contains all of Git’s data and history.

You can check the repo status:

bash
git status

If you have not added or committed anything yet, you will see something like:

text
On branch master
No commits yet
Untracked files:
  (use "git add <file>..." to include in what will be committed)
    app.py
    requirements.txt

Tracking Files: Add and Commit

Git has three main states for files:

Example: First Commit

Imagine you create a simple backend entry point:

python
# app.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
    return {"message": "Hello, world"}

Now you want to save this version in Git.

  1. See what changed:
bash
   git status
  1. Stage the file:
bash
   git add app.py
  1. Commit it:
bash
   git commit -m "Add basic FastAPI app"

The -m flag adds a commit message. Messages should briefly explain what and optionally why.

Important rule:
Each commit should represent a logical, small change. Avoid huge commits that mix many unrelated changes.

Staging multiple files

You can stage all new and modified files:

bash
git add .

Then commit:

bash
git commit -m "Implement user model and basic routes"

Or stage specific files:

bash
git add app.py models.py
git commit -m "Refactor user model and endpoints"

Seeing What Changed

You often want to see exactly what has changed before committing.

bash
  git diff
bash
  git diff --staged

Example output:

diff
diff --git a/app.py b/app.py
index 3f3c0c1..a9f8b6d 100644
--- a/app.py
+++ b/app.py
@@ -1,5 +1,8 @@
 from fastapi import FastAPI
 app = FastAPI()
+
+@app.get("/health")
+def health_check():
+    return {"status": "ok"}

This diff shows that you added a /health endpoint. This is very common in backend apps.

Ignoring Files with .gitignore

Some files should not be tracked. Typical examples in backend projects:

You put these patterns into a file named .gitignore in your project root.

Example .gitignore for a Python backend:

text
# Python
__pycache__/
*.pyc
# Environments
.env
venv/
.venv/
# IDEs
.vscode/
.idea/
# Logs
logs/
*.log

After adding .gitignore, run:

bash
git add .gitignore
git commit -m "Add .gitignore for Python backend project"

If you accidentally committed a file that should be ignored, you must remove it from the repository history. At minimum, run:

bash
git rm --cached secret.env
git commit -m "Stop tracking secret.env"

But if secrets were committed, you should change the secret immediately in your production systems.

Viewing History

To see the list of commits:

bash
git log

You will see something like:

text
commit 9e7c6f5a1b...
Author: Alice Backend <alice@example.com>
Date:   Mon Aug 26 10:12:34 2026 +0000
    Add user registration endpoint
commit 3a2b1c4d2e...
Author: Alice Backend <alice@example.com>
Date:   Mon Aug 26 09:45:12 2026 +0000
    Initialize FastAPI project

Shorter format:

bash
git log --oneline

Example:

text
9e7c6f5 Add user registration endpoint
3a2b1c4 Initialize FastAPI project

This helps you see the progression of your backend features.

Undoing Local Changes Safely

You will often need to undo mistakes. There are several levels of "undo."

1. Undo uncommitted changes in a file

If you changed a file but have not staged it and want to revert it to the last commit:

bash
git checkout -- app.py

This discards your local modifications to app.py.

2. Unstage a file

If you did git add app.py by mistake:

bash
git reset HEAD app.py

This moves the file out of the staging area, but keeps your edits in the working directory.

3. Revert a committed change

If a commit broke your backend and you want to create a new commit that goes back:

  1. Find the commit hash with git log. Example: 9e7c6f5.
  2. Run:
bash
   git revert 9e7c6f5

This creates a new commit that undoes the changes of 9e7c6f5. This is safe for shared branches.

Important rule:
On branches that others are already using, prefer git revert over rewriting history.

Branches for Backend Features

Branches let you work on features independently of the main code.

Creating and switching branches

See existing branches:

bash
git branch

Create a new branch:

bash
git branch feature/user-registration

Switch to it:

bash
git checkout feature/user-registration

Or create and switch in one command:

bash
git checkout -b feature/user-registration

Now any commits you make are recorded on this branch, not on main.

Example workflow:

bash
git checkout -b feature/user-registration
# edit files: add registration endpoint
git add app.py models.py
git commit -m "Add basic user registration endpoint"

Later, you will merge this branch back into main.

Merging Branches

When a feature is ready, you usually:

  1. Make sure your feature branch has the latest changes from main.
  2. Merge the feature branch into main.

Example:

bash
# Be on main
git checkout main
# Get latest remote main (explained later)
git pull
# Merge the feature branch
git merge feature/user-registration

If files were changed in both branches, Git might not know which version to keep. This is a merge conflict.

Example of a merge conflict

Suppose two branches both edit app.py at the same place. After merging, Git might show:

text
<<<<<<< HEAD
@app.get("/health")
def health_check():
    return {"status": "ok"}
=======
@app.get("/health")
def health_check():
    return {"status": "healthy"}
>>>>>>> feature/update-health-message

You must edit the file to resolve the conflict. For example, pick one version:

python
@app.get("/health")
def health_check():
    return {"status": "ok"}

Then:

bash
git add app.py
git commit -m "Resolve merge conflict in health_check"

You will handle many conflicts in real backend projects when several developers touch the same logic.

Working with Remote Repositories

Remotes let you share your code and collaborate.

You typically start by cloning an existing remote repository rather than running git init.

Cloning a repository

From a remote URL (for example from GitHub):

bash
git clone https://github.com/your-username/my-api.git

This:

Change into the folder:

bash
cd my-api

Checking remotes

See configured remotes:

bash
git remote -v

Example:

text
origin  https://github.com/your-username/my-api.git (fetch)
origin  https://github.com/your-username/my-api.git (push)

Pulling changes

To get the latest changes from the remote branch you are on:

bash
git pull

This is a combination of:

bash
git fetch
git merge

git fetch downloads new commits. git merge integrates them into your local branch.

Pushing changes

Once you have local commits you want to share:

bash
git push

If this is a new branch not yet on the remote:

bash
git push -u origin feature/user-registration

The -u flag sets origin/feature/user-registration as the default remote branch. Next time, you can simply run:

bash
git push

Common Git Commands Cheat Sheet

Here is a small table you can refer to while learning:

ActionCommand example
Initialize a repogit init
Clone a repogit clone <url>
Check statusgit status
Stage a filegit add app.py
Stage all changesgit add .
Commit staged changesgit commit -m "Message"
See historygit log or git log --oneline
See unstaged changesgit diff
See staged changesgit diff --staged
Create a branchgit branch feature/auth
Switch branchgit checkout feature/auth
Create and switchgit checkout -b feature/auth
Merge a branch into current branchgit merge feature/auth
Add a remotegit remote add origin <url>
Show remotesgit remote -v
Pull from remotegit pull
Push to remotegit push
Undo local file changesgit checkout -- app.py
Unstage a filegit reset HEAD app.py
Revert a commitgit revert <commit-hash>

Example: Simple Backend Workflow with Git

Walk through a small, realistic example.

  1. Clone a backend project
bash
   git clone https://github.com/example-org/todo-api.git
   cd todo-api
  1. Create a branch for a new feature
bash
   git checkout -b feature/add-due-date
  1. Edit code

Update models.py and routes.py to add a due_date field to tasks.

  1. Check what changed
bash
   git status
   git diff
  1. Stage and commit
bash
   git add models.py routes.py
   git commit -m "Add due_date field to Task model and endpoints"
  1. Push to remote
bash
   git push -u origin feature/add-due-date
  1. Open a pull request / merge request

In GitHub or GitLab, you select the branch feature/add-due-date and open a PR into main. Your teammates review your changes.

  1. Update local main after merge

After the feature is merged:

bash
   git checkout main
   git pull

This is the pattern you will repeat in almost every backend project.

Good Practices for Backend Projects with Git

Important rule:
Never commit the .env file or any file containing production secrets. Use .gitignore and secret management tools instead.

With these basics, you can already participate in real backend projects, share your work, and collaborate through GitHub or GitLab, which you will explore in the next chapters.

Views: 6

Comments

Please login to add a comment.

Don't have an account? Register now!