3.7. Git
Table of Contents
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:
- Save versions of your code over time
- Go back to older versions when something breaks
- Work with other developers on the same project without overwriting each other
- Review and discuss code changes in pull requests or merge requests
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:
- Which files changed
- What changed inside those files
- Who changed them and when
- Messages explaining why the change was made
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:
my-api/
app.py
models.py
requirements.txt
README.mdWhen 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:
- Local repository: lives on your machine, inside your project folder
- Remote repository: lives on a server, for example GitHub or GitLab
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:
- Clone a remote repository to create a local copy.
- Work locally, changing files and committing.
- Push your commits back to the remote.
- Your teammates pull those commits into their own local copies.
Basic Git Concepts
Here are the most important concepts you will use daily.
| Concept | What it is | Simple analogy |
|---|---|---|
| Repository (repo) | A project folder tracked by Git, with its full history | A library with all editions of a book |
| Commit | A snapshot of your changes with a message | A saved game checkpoint |
| Branch | A line of development, separate from others | A different storyline in your game |
| Working tree | Your current files on disk | The page you are currently editing |
| Staging area | A temporary area where you prepare changes for a commit | A basket of pages you are about to save |
| Remote | A copy of the repo on another computer or server | A 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:
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:
git statusIf you have not added or committed anything yet, you will see something like:
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
app.py
requirements.txtTracking Files: Add and Commit
Git has three main states for files:
- Untracked: Git does not know about this file yet
- Tracked but modified: Git knows the file, and it has changes not yet committed
- Staged: The file is ready to be committed
Example: First Commit
Imagine you create a simple backend entry point:
# 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.
- See what changed:
git status- Stage the file:
git add app.py- Commit it:
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:
git add .Then commit:
git commit -m "Implement user model and basic routes"Or stage specific files:
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.
- Show changes that are not staged:
git diff- Show changes that are staged and will be committed:
git diff --stagedExample output:
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:
- Virtual environment folders (for example
venv/) - Compiled files (for example
__pycache__/) - Local configuration with secrets (for example
.env) - Logs (for example
logs/)
You put these patterns into a file named .gitignore in your project root.
Example .gitignore for a Python backend:
# Python
__pycache__/
*.pyc
# Environments
.env
venv/
.venv/
# IDEs
.vscode/
.idea/
# Logs
logs/
*.log
After adding .gitignore, run:
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:
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:
git logYou will see something like:
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 projectShorter format:
git log --onelineExample:
9e7c6f5 Add user registration endpoint
3a2b1c4 Initialize FastAPI projectThis 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:
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:
git reset HEAD app.pyThis 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:
- Find the commit hash with
git log. Example:9e7c6f5. - Run:
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.
mainormaster: usually the stable branch- Feature branches: for example
feature/user-registration,bugfix/fix-login-500
Creating and switching branches
See existing branches:
git branchCreate a new branch:
git branch feature/user-registrationSwitch to it:
git checkout feature/user-registrationOr create and switch in one command:
git checkout -b feature/user-registration
Now any commits you make are recorded on this branch, not on main.
Example workflow:
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:
- Make sure your feature branch has the latest changes from
main. - Merge the feature branch into
main.
Example:
# Be on main
git checkout main
# Get latest remote main (explained later)
git pull
# Merge the feature branch
git merge feature/user-registrationIf 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:
<<<<<<< HEAD
@app.get("/health")
def health_check():
return {"status": "ok"}
=======
@app.get("/health")
def health_check():
return {"status": "healthy"}
>>>>>>> feature/update-health-messageYou must edit the file to resolve the conflict. For example, pick one version:
@app.get("/health")
def health_check():
return {"status": "ok"}Then:
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):
git clone https://github.com/your-username/my-api.gitThis:
- Creates a folder
my-api - Sets up a local repository
- Connects it to the remote named
origin
Change into the folder:
cd my-apiChecking remotes
See configured remotes:
git remote -vExample:
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:
git pullThis is a combination of:
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:
git pushIf this is a new branch not yet on the remote:
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:
git pushCommon Git Commands Cheat Sheet
Here is a small table you can refer to while learning:
| Action | Command example |
|---|---|
| Initialize a repo | git init |
| Clone a repo | git clone <url> |
| Check status | git status |
| Stage a file | git add app.py |
| Stage all changes | git add . |
| Commit staged changes | git commit -m "Message" |
| See history | git log or git log --oneline |
| See unstaged changes | git diff |
| See staged changes | git diff --staged |
| Create a branch | git branch feature/auth |
| Switch branch | git checkout feature/auth |
| Create and switch | git checkout -b feature/auth |
| Merge a branch into current branch | git merge feature/auth |
| Add a remote | git remote add origin <url> |
| Show remotes | git remote -v |
| Pull from remote | git pull |
| Push to remote | git push |
| Undo local file changes | git checkout -- app.py |
| Unstage a file | git reset HEAD app.py |
| Revert a commit | git revert <commit-hash> |
Example: Simple Backend Workflow with Git
Walk through a small, realistic example.
- Clone a backend project
git clone https://github.com/example-org/todo-api.git
cd todo-api- Create a branch for a new feature
git checkout -b feature/add-due-date- Edit code
Update models.py and routes.py to add a due_date field to tasks.
- Check what changed
git status
git diff- Stage and commit
git add models.py routes.py
git commit -m "Add due_date field to Task model and endpoints"- Push to remote
git push -u origin feature/add-due-date- 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.
- Update local main after merge
After the feature is merged:
git checkout main
git pullThis is the pattern you will repeat in almost every backend project.
Good Practices for Backend Projects with Git
- Commit often, but meaningfully: each commit should be a logical unit, for example "Add login endpoint" or "Validate request body for registration".
- Write helpful messages: "Fix bug" is not helpful. "Fix 500 error when email is missing in registration" is.
- Use branches per feature: do not develop everything on
main. - Do not commit generated or build files: for example migrations can be committed, but compiled binaries should usually not be.
- Always pull before starting new work: keep your local branch updated before editing.
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
KAHIBARO