Back to blog

Complete Git guide for freelance developers

October 1, 2024•Updated on September 5, 2026•Dedimarco
git development freelance productivity
Complete Git guide for freelance developers

In short: As of September 5, 2026, use a simplified GitHub Flow for most freelance projects: keep main deployable, give each task a short-lived branch, and merge through a pull request. Add Conventional Commits to clarify history. Reserve GitFlow for projects with planned releases or several versions maintained in parallel.

Git becomes demanding when you switch among several projects, clients, and teams. A consistent branching strategy, explicit commits, and a few checks before every push prevent costly mistakes.

Which branching strategy should you choose?

Your choice of branch strategy depends on project size, deployment frequency, and the number of contributors.

GitFlow: the classic method

The GitFlow model, presented by Vincent Driessen in 2010, uses long-lived branches and a strict hierarchy. Its author now recommends a simpler workflow for continuous delivery, while retaining GitFlow for explicitly versioned software or products that support several versions.

main ─────────────────────────────────────► (production)
  │                                          ▲
  ├── develop ───────────────────────────────┤ (integration)
  │     │          │          │              │
  │     ├── feature/login ──┘              │
  │     ├── feature/api ────┘              │
  │                                          │
  │     └── release/1.0 ────────────────────┘
  │
  └── hotfix/fix-bug ──────────────────────►┘

The branches:

  • main: production code, always stable
  • develop: feature integration
  • feature/*: new feature development
  • release/*: version preparation
  • hotfix/*: urgent production fixes

When to use it: projects with planned release cycles, mobile apps with App Store/Play Store versioning, regulated environments requiring strict deployment control.

GitHub Flow: simplicity

The official GitHub Flow documentation, consulted on September 5, 2026 describes a lightweight workflow: one branch per change, explicit commits, a pull request, and then a merge into the default branch.

main ─────●─────●─────●─────●──────► (always deployable)
            ▲         ▲
            │         │
       feature/A  feature/B
       (PR + review) (PR + review)

The principle is simple:

  1. Create a branch from main
  2. Work on the feature
  3. Open a pull request for feedback or validation.
  4. Merge into main when the change is ready.
  5. Delete the branch when it is no longer needed.

Trunk-based development: expert mode

Trunk-based development pushes the idea further: work joins the main branch frequently, either directly or from short-lived branches.

# Ephemeral branch
git checkout -b quick-fix
# Changes...
git commit -am "fix: quick fix"
git push origin quick-fix
# Prompt review and merge

# Or directly on main (for small changes)
git checkout main
# Changes...
git commit -am "docs: update README"
git push origin main

In this example, incomplete features are hidden behind feature flags:

if (featureFlag.isEnabled('new-payment-flow')) {
  // New payment logic
} else {
  // Legacy logic
}

My choice as a freelancer

For most freelance projects, my recommendation is an adapted GitHub Flow:

  • Solo project: keep main deployable and create a short-lived branch for each meaningful task.
  • Team project: add a pull request, automated checks, and the validation environment required by the client.
  • Planned releases or versions maintained in parallel: consider GitFlow, without adding any branch that the release process does not justify.

Why adopt Conventional Commits?

The Conventional Commits 1.0.0 specification, consulted on September 5, 2026 defines a lightweight convention that adds human-readable and machine-readable meaning to commit messages:

<type>[optional scope]: <description>

[optional body]

[optional footer]

Common types:

  • feat: new feature defined by the specification
  • fix: bug fix defined by the specification
  • docs: documentation, an allowed complementary type
  • style: formatting with no functional impact
  • refactor: refactoring
  • test: addition or modification of tests
  • chore: maintenance task
  • perf: performance optimization

Examples:

git commit -m "feat(auth): add OAuth2 login with Google"
git commit -m "fix(cart): prevent duplicate items on rapid clicks"
git commit -m "docs: update API documentation for v2 endpoints"
git commit -m "perf(images): implement WebP conversion pipeline"

This convention makes history easier to read and lets tools generate changelogs or determine a semantic version change. Types other than feat and fix remain team conventions, so document them.

Which Git practices should you apply daily?

The .gitignore from day one

Every project should start with a proper .gitignore:

# Dependencies
node_modules/
vendor/

# Environment
.env
.env.local
.env.*.local

# Build
dist/
build/

# IDE
.vscode/
.idea/

# OS
.DS_Store
Thumbs.db

# Logs
*.log
npm-debug.log*

Handling merge conflicts

Conflicts are inevitable. Here’s a systematic method:

# Update main
git checkout main && git pull

# Rebase your feature branch onto main
git checkout feature/my-feature
git rebase main

# If conflict occurs, resolve and continue
git add <files>
git rebase --continue

# Or abort the rebase if needed
git rebase --abort

Rebase reapplies your commits onto a new base and can preserve a linear history. Use it on your working branch, but avoid rewriting a branch that others already use unless the team has agreed to it:

# History with merge (less readable)
*   Merge branch 'feature/login' into main
|\
| * feat: add login form
|/
* feat: add auth module

# History with rebase (cleaner)
* feat: add login form
* feat: add auth module

Git aliases to save time

# ~/.gitconfig
[alias]
  st = status -sb
  co = checkout
  br = branch
  cm = commit -m
  lg = log --oneline --graph --all --decorate
  unstage = reset HEAD --
  last = log -1 HEAD --stat
  undo = reset --soft HEAD~1

How do you collaborate across several clients?

Case 1: you join an existing project

# Clone the repo
git clone <url>
cd <project>

# Understand the branch structure
git branch -a

# Create your working branch
git checkout -b freelance/marc-feature main

# Follow existing conventions
git log --oneline -20

Case 2: you manage a project for a client

# Recommended structure
git init
git checkout -b main

# Protect main (on GitHub/GitLab)
# - Require pull request reviews
# - Require status checks
# - No force push

# Branch per task
git checkout -b feature/redesign-homepage

Case 3: you collaborate with in-house developers

# Sync regularly
git fetch origin
git rebase origin/main

# Clear PR with description
gh pr create --title "feat: redesign homepage" \
  --body "## Changes
- New hero section
- Updated navigation
- Mobile responsive layout

## Testing
- [x] Desktop Chrome/FF/Safari
- [x] Mobile iOS/Android"

Which tools complement this Git workflow?

Git hooks with Husky

The Husky getting-started documentation, consulted on September 5, 2026 says that husky init creates a pre-commit hook in .husky/ and updates the prepare script. You can then run the checks appropriate to the project:

# Installation
npm install -D husky
npx husky init
# .husky/pre-commit
npx lint-staged
// package.json
{
  "lint-staged": {
    "*.{js,ts}": ["eslint --fix", "prettier --write"],
    "*.{css,scss}": ["stylelint --fix", "prettier --write"],
    "*.md": ["prettier --write"]
  }
}

Git Bisect to find the offending commit

# Git bisect finds the commit that introduced a bug
git bisect start
git bisect bad           # Current commit is broken
git bisect good v1.0     # This version worked

# Git automatically checks out intermediate commits
# Test and indicate good/bad
git bisect good          # or git bisect bad

# Repeat until the offending commit is found
git bisect reset         # Return to HEAD

Conclusion

Start simple: an adapted GitHub Flow, consistent Conventional Commits, and one branch per task. Add rules only when a client, team, or release cycle justifies them.

When handling several clients, keep repositories strictly separate and check the remote, branch, and active Git identity before every push. Document each team’s choices in its CONTRIBUTING.md.

Sources

Frequently asked questions

Which Git workflow should you use when working solo?

Use a simplified GitHub Flow: keep `main` deployable, create a short-lived branch for each task, then open a pull request before merging. Add GitFlow only when the project requires planned releases or support for multiple versions.

Should freelancers use Conventional Commits?

Yes, if you apply the convention consistently. Prefixes such as `feat`, `fix`, and `docs` make history easier to read and can support changelog and release automation.

How do you manage several clients with Git without mixing projects?

Keep a separate repository and configuration for each client, follow their conventions, and use one branch per task. Always check the repository, branch, and Git identity before pushing.

Is GitFlow still recommended for freelancers?

Not by default. GitFlow remains relevant for explicitly versioned software or when several versions must be supported, but a simpler flow is usually a better fit for continuous delivery.