Git for PHP Developers: Setup and Daily Workflow

Learning Git for PHP developers is one of the most valuable skills you can add to your workflow. Most PHP tutorials skip Git entirely or mention it in one line – “initialize a repository and commit your code.” That’s not enough. Git is the tool you’ll use every single day, and getting the workflow right from the start saves significant pain later.

This guide covers Git setup specifically for PHP projects – configuration, the daily commit workflow, what belongs in your .gitignore, how to write commit messages that actually help you later, and the commands you’ll run dozens of times per week. No theory, just the practical workflow.

Installing Git

Windows

Download Git from git-scm.com and run the installer. Accept the defaults – they’re sensible. During installation, select “Git from the command line and also from 3rd-party software” when asked about PATH adjustment.

Verify the installation:

git --version

Output:

git version 2.44.0.windows.1

Linux (Ubuntu/Debian)

sudo apt update
sudo apt install git
git --version

macOS

# Install via Homebrew
brew install git
git --version

First-Time Configuration

Do this once after installation. Every commit you make will be stamped with this name and email:

git config --global user.name "Your Name"
git config --global user.email "you@example.com"

Set VS Code as your default editor – useful when Git opens an editor for commit messages or merge conflicts:

git config --global core.editor "code --wait"

Enable colored output so diffs and status messages are readable:

git config --global color.ui true

Set the default branch name to main – modern convention and matches GitHub’s default:

git config --global init.defaultBranch main

Verify everything looks correct:

git config --list

Output:

user.name=Kapil Verma
user.email=kapil@example.com
core.editor=code --wait
color.ui=true
init.defaultbranch=main

Initializing a PHP Project

Navigate to your project directory and initialize Git:

mkdir my-php-project
cd my-php-project
git init

Output:

Initialized empty Git repository in /var/www/html/my-php-project/.git/

For an existing PHP project:

cd /var/www/html/my-existing-project
git init
git add .
git commit -m "Initial commit"

The PHP .gitignore File

This is the most important file you create in any PHP project. It tells Git which files to ignore – vendor directories, environment files, logs, and editor-specific files that have no business in version control.

Create .gitignore in your project root before your first commit:

# PHP Dependencies
/vendor/
composer.phar

# Environment and configuration
.env
.env.local
.env.*.local
config/local.php
config/database.local.php

# Laravel specific
/bootstrap/cache/
/storage/*.key
/public/hot
/public/storage
Homestead.json
Homestead.yaml

# WordPress specific
wp-config.php
/wp-content/uploads/
/wp-content/cache/
/wp-content/upgrade/
*.log

# Logs and temporary files
/logs/
*.log
/tmp/
/cache/

# IDE and editor files
.idea/
.vscode/
*.swp
*.swo
.DS_Store
Thumbs.db

# Testing
/coverage/
.phpunit.result.cache

# Build files
/node_modules/
/public/build/
/public/mix-manifest.json

The two most critical entries are /vendor/ and .env. Committing vendor means pushing thousands of dependency files that Composer regenerates in seconds. Committing .env means putting database passwords and API keys into version control – a security problem that’s difficult to fully undo once it’s in the history.

Understanding the Three States

Git has three places your code lives – understanding this makes every command make sense:

Working Directory → Staging Area → Repository
     (modified)       (staged)      (committed)

Working directory is where you edit files. Staging area is where you prepare your next commit. Repository is the permanent history.

Check which state your files are in at any time:

git status

Output on a fresh PHP project:

On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .gitignore
        index.php
        src/

nothing added to commit but untracked files present

The Daily Git for PHP Developers Workflow

This is the sequence you’ll repeat dozens of times every week. Internalize this and Git becomes automatic:

Step 1: Check What Changed

git status

Always start here. It tells you exactly what’s modified, what’s staged, and what’s untracked.

Step 2: See the Actual Changes

# See unstaged changes
git diff

# See changes in a specific file
git diff src/UserController.php

Output:

diff --git a/src/UserController.php b/src/UserController.php
index a3b2c1d..f4e5d6e 100644
--- a/src/UserController.php
+++ b/src/UserController.php
@@ -15,6 +15,12 @@ class UserController
     public function store(Request $request)
     {
+        $validated = $request->validate([
+            'name'  => 'required|string|max:255',
+            'email' => 'required|email|unique:users',
+        ]);
+
+        User::create($validated);

Lines starting with + are additions. Lines starting with - are removals. Review this before staging anything – it’s your last easy chance to catch mistakes.

Step 3: Stage Your Changes

# Stage a specific file
git add src/UserController.php

# Stage a directory
git add src/

# Stage everything in the project
git add .

# Stage parts of a file interactively
git add -p src/UserController.php

git add -p is worth knowing. It shows each changed chunk individually and asks whether to stage it. Useful when one file contains two unrelated changes and you want to commit them separately.

Step 4: Verify What You’re About to Commit

git diff --staged

This shows staged changes – exactly what will be in your next commit. Always check this before committing on important changes.

Step 5: Commit

git commit -m "Add validation to UserController store method"

Output:

[main 3f7a9b2] Add validation to UserController store method
 1 file changed, 6 insertions(+)

Writing Good Commit Messages

A commit message is a note to your future self and anyone else who works on the code. “fixed stuff” and “WIP” are useless when you’re debugging a production issue at 11pm six months later.

The format that works:

# Good commit messages - specific and clear
git commit -m "Add email validation to registration form"
git commit -m "Fix cURL timeout on product scraper - increase to 30s"
git commit -m "Remove deprecated mysql_connect - replace with PDO"
git commit -m "Add CSRF token to login form"
git commit -m "Fix SQL injection vulnerability in search query"

# Bad commit messages - useless for debugging
git commit -m "fix"
git commit -m "WIP"
git commit -m "changes"
git commit -m "update"
git commit -m "asdfgh"

The rule: if you can’t complete the sentence “This commit will…” with your message, rewrite it. “This commit will add email validation to registration form” – clear. “This commit will fix” – meaningless.

Viewing History

# Full commit history
git log

# Condensed one-line format - most useful day to day
git log --oneline

# Last 5 commits
git log --oneline -5

# Commits by a specific author
git log --oneline --author="Kapil"

# Commits that changed a specific file
git log --oneline -- src/UserController.php

# Visual graph showing branches
git log --oneline --graph --all

Output of git log –oneline -5:

3f7a9b2 Add validation to UserController store method
8c4d1e5 Add PDO connection with error handling
2a9f3b1 Create users table migration
7e2c8d4 Add .gitignore for PHP project
1b5a6f9 Initial commit

This is your project’s timeline. Each line is a save point you can return to.

Connecting to GitHub

Create a repository on GitHub then connect your local project:

# Add the remote repository
git remote add origin https://github.com/yourusername/my-php-project.git

# Verify the remote was added
git remote -v

# Push your code for the first time
git push -u origin main

Output:

origin  https://github.com/yourusername/my-php-project.git (fetch)
origin  https://github.com/yourusername/my-php-project.git (push)

Enumerating objects: 12, done.
Counting objects: 100% (12/12), done.
Writing objects: 100% (12/12), 3.42 KiB | 3.42 MiB/s, done.
To https://github.com/yourusername/my-php-project.git
 * [new branch]      main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

After the first push with -u flag, future pushes are just:

git push

Cloning an Existing PHP Project

When joining a project or setting up on a new machine:

# Clone the repository
git clone https://github.com/username/php-project.git

# Clone into a specific directory name
git clone https://github.com/username/php-project.git my-local-name

cd php-project

# Install PHP dependencies
composer install

# Copy environment file
cp .env.example .env

# Set up your local configuration
nano .env

Always run composer install after cloning a PHP project. The vendor directory is in .gitignore so it won’t be in the repository – Composer recreates it from composer.lock.

Useful Git Aliases for PHP Developers

Set up shortcuts for the commands you run most often:

# Short status
git config --global alias.st status

# Short log - one line per commit
git config --global alias.lg "log --oneline --graph --all -20"

# Undo last commit but keep changes staged
git config --global alias.undo "reset --soft HEAD~1"

# Show what changed in the last commit
git config --global alias.last "show --stat HEAD"

Now instead of typing git status you type git st. Small thing, adds up over thousands of uses:

git st    # git status
git lg    # visual log last 20 commits
git undo  # undo last commit safely
git last  # what did I just commit?

Quick Reference: Daily Commands

CommandWhat It Does
git statusShow modified, staged, and untracked files
git diffShow unstaged changes
git diff –stagedShow staged changes about to be committed
git add .Stage all changed files
git add -pStage changes interactively chunk by chunk
git commit -m “message”Commit staged changes with a message
git pushPush commits to remote repository
git pullFetch and merge remote changes
git log –onelineView condensed commit history
git log –oneline — fileHistory of a specific file

Frequently Asked Questions

Should I commit composer.lock to Git?

Yes – always commit composer.lock but never commit the /vendor/ directory. The lock file records the exact versions of every dependency installed. When another developer runs composer install, they get identical versions to yours. Without the lock file, composer install might install newer patch versions that behave differently. The vendor directory itself is regenerated from the lock file and has no place in version control.

I accidentally committed my .env file. What do I do?

Three steps. First, add .env to your .gitignore immediately. Second, remove it from Git’s tracking without deleting the file:

git rm --cached .env
git commit -m "Remove .env from version control"
git push

Third – and this is critical – rotate every credential that was in that file. Change your database password, regenerate API keys, update your application key. The file is in the repository history even after removal. If the repository was ever public or pushed to a remote, assume those credentials are compromised.

What is the difference between git fetch and git pull?

git fetch downloads changes from the remote repository but doesn’t merge them into your working branch. git pull fetches and merges in one step. Use git fetch when you want to see what changed on the remote before deciding whether to merge. Use git pull when you’re ready to update your local branch immediately.

How often should I commit in a PHP project?

Commit when you complete a logical unit of work – not necessarily a full feature, but something that stands on its own. Adding a method, fixing a bug, adding validation to a form, writing a database migration. Small focused commits are easier to understand in the log, easier to revert if something goes wrong, and easier to review in pull requests. Committing once a day with everything bundled together makes Git history nearly useless.

What should I do if I committed to the wrong branch?

If you haven’t pushed yet, undo the last commit while keeping your changes:

# Undo last commit, keep changes staged
git reset --soft HEAD~1

# Switch to the correct branch
git checkout correct-branch

# Commit on the right branch
git commit -m "Your message"

If you’ve already pushed, the situation is more complex – that’s covered in Post 3 of this series on undoing mistakes in Git.


Summary

The Git workflow for PHP developers comes down to a repeating cycle:

  • Check status before touching anything – git status
  • Review changes before staging – git diff
  • Stage intentionallygit add -p for precision, git add . for everything
  • Commit with meaning – messages that explain what and why, not just “update”
  • Push regularly – your remote is your backup

The .gitignore file is not optional for PHP projects. Set it up before the first commit and include /vendor/, .env, logs, and editor files as a minimum.

The next post in this series covers Git branching for PHP projects – how to use feature branches for new work, hotfix branches for production bugs, and how to merge cleanly without losing history. If you’re using Git for a PHP project alongside a framework, the PHP project setup guide covers the full project structure including Git initialization from scratch.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top