Two developers share a Laravel project by emailing ZIP files or editing directly on the server, and one day a feature that worked yesterday is gone because someone overwrote it. This is extremely common in small teams and among freelancers who start working in pairs. Git and GitHub solve it, but only when everyone follows the same workflow.
This is not a list of every Git command. It covers the daily workflow that is enough for a team of two to ten: branching, committing, opening pull requests, reviewing code, and resolving conflicts calmly.
Prepare the Repository
Before anyone collaborates, make sure nothing private is tracked. Laravel's default .gitignore already excludes vendor, node_modules, and .env. Double-check it and commit an .env.example with variable names but no secrets.
# .gitignore (key Laravel entries)
/vendor
/node_modules
/public/build
/public/storage
/storage/*.key
.env
.env.backup
.phpunit.result.cache
If an .env containing database passwords or API keys was ever committed, deleting it in a later commit is not enough because it stays in history. Rotate every exposed credential immediately; these 10 security practices cover the rest of the basics.
Choose a Branching Workflow
| Workflow | How it works | Best for | Notes |
|---|---|---|---|
| GitHub Flow | One always-deployable main; each change on its own branch, merged through a pull request | Small teams, web apps that deploy often | Simplest; the recommended starting point |
| Git Flow | main, develop, feature/*, release/*, hotfix/* | Products with scheduled, versioned releases | More ceremony than most small teams need |
| Trunk-based | Small, frequent commits to main; unfinished work hidden behind feature flags | Experienced teams with strong automated tests | Requires discipline and solid CI |
For most small teams and agencies, GitHub Flow is enough. Add a staging branch only if you actually run a separate staging server.
The Daily Loop
- Update your local main so new work starts from the latest code.
- Create a descriptive branch such as
feature/sales-reportorfix/negative-stock. - Commit small and often, one logical change per commit.
- Push and open a pull request, even as a draft, so the team can see what is in progress.
- Request review and address feedback with follow-up commits.
- Merge once approved and checks pass, then delete the branch.
git switch main
git pull origin main
git switch -c feature/sales-report
# ... edit code ...
git add app/Http/Controllers/ReportController.php resources/views/reports
git commit -m "Add daily sales report per cashier"
git push -u origin feature/sales-report
# then click "Compare & pull request" on GitHub
git switch, available since Git 2.23, is a clearer replacement for git checkout when changing branches.
Commits and Pull Requests That Help the Team
Write commit messages for a teammate reading them six months from now. Use a short imperative sentence that says what changed, such as "Fix discount calculation for quantities over 10", not "update" or "fix bug". Many teams adopt Conventional Commits prefixes like feat:, fix:, and docs: to make history scannable.
A good PR description answers what changed, why, and how to test it. Save a template at .github/pull_request_template.md so it appears on every new PR:
## What changed
-
## Why
Linked issue:
## How to test
1. php artisan migrate
2. Open /reports/sales and pick today's date
## Checklist
- [ ] New migration? It can be rolled back
- [ ] No secrets in code
- [ ] Checked on a mobile screen
Schema changes deserve extra scrutiny in review, because a bad migration can damage production data; see safe database migrations in Laravel.
Code Review That Works
- Keep PRs small. Changes under roughly 300 to 400 lines get far more careful review than thousand-line PRs (a practical rule of thumb, not a standard).
- Review logic and risk, not style. Let tools like Laravel Pint handle formatting.
- Phrase comments as questions or suggestions: "Does this query need eager loading?" rather than "This is wrong."
- Agree on turnaround, for example reviews within one working day.
Resolving Merge Conflicts
A conflict happens when two branches change the same lines. Git cannot pick a winner, so it marks the spot and asks you.
- Bring your branch up to date:
git pull origin main, orgit rebase origin/mainif your team rebases. - Open each flagged file and find the
<<<<<<<,=======, and>>>>>>>markers. - Decide the final content: keep one side or combine both, and remove every marker.
- Run the app and tests to confirm the merged result works.
git addthe files, thengit commit(orgit rebase --continue).
VS Code shows "Accept Current", "Accept Incoming", and "Accept Both" buttons that make this quicker. Frequent conflicts usually mean branches live too long, so merge more often.
GitHub Settings Worth Turning On
- Branch protection on main: require PRs, at least one approval, and block force pushes.
- GitHub Actions running
php artisan testand Pint on every PR. - Secret scanning and Dependabot to catch leaked credentials and vulnerable dependencies.
- Private repositories for client or commercial code, with access reviewed periodically.
Common Mistakes and How to Recover
Committed straight to main
If you have not pushed, move the work to a new branch with git switch -c feature/x, then reset main with git switch main and git reset --hard origin/main. Confirm the work is safe on the new branch before resetting.
Typo in the last commit message
Before pushing, use git commit --amend. If it is already on a shared branch, leave it.
Need to undo a commit already on main
Use git revert <hash>, which creates a new commit that reverses the change. Never rewrite history on a shared branch.
Team Checklist Before You Start
.gitignorereviewed and.env.examplecommitted.- Branching workflow agreed and written in the README.
- Main protected with required PRs and approvals.
- PR template in place.
- Tests and formatting run in GitHub Actions.
- A setup guide for new teammates to run the project locally.
The same workflow applies when your team customizes ready-made source code, such as a package from GudangCode: commit the original as the first commit, then do customizations on branches so both upstream updates and your own changes stay traceable, as described in customizing source code without breaking it.