Your trouble comes from working in the
main branch directly, don't do that. Instead, follow a feature branch workflow where every feature is developed in a dedicated branch. This way, every developer can work in their own branch without other people interfering. You can even configure branch protection rules in Github (if you're using Github) to prevent everyone from pushing to the
main branch directly. Instead, merging finished features is done through pull requests. You can allow developers to merge pull requests as soon as they're opened up, though I highly recommend requiring at least one approving review from another developer. This has the added benefit of having at least two pairs of eyes on every feature that gets introduced to the project, which allows you to catch bugs early and increase everyone's knowledge of the entire codebase.
If you're working in your own branch, other developers merging something into the main branch on the remote won't interfere with your work and you can update your local main branch whenever you want without conflicts. You still might have to fix conflicts between your changes and the changes introduced, but you can do so at your leisure and only need to do so when your feature is done.
With this workflow, the regular process looks a little like this:
- Developer A(lice) and B(ob) both start work on a feature. Both create a local branch (
feature-b, respectively) based on the main branch at this point in time.
- While Bob is still working, Alice is done. She pushes her branch to Github and opens a pull request. Charlie reviews the request and approves it, Alice merges it into main (and deletes
branch-a on Github). Now Alice can checkout the
main branch locally, pull the merged changes from Github and delete her
feature-a branch. Now she can create a new branch for the next feature she is going to work on based on the current
- Now Bob is finished with his feature. Once all his changes are committed in
feature-b, Bob checks out the
main branch and pulls the latest changes. Then he checks out
feature-b again. Now he can either merge
main into his branch (
git merge main) or rebase his branch on
git rebase main). Both of those operations will perform a three-way merge by default and report any conflicts. Oftentimes, there won't be any conflicts, in this case Bob can continue to open a pull request.
- Let's assume there are conflicts. Now is the time to resolve them, the same way you would resolve other conflicts in git. Once all conflicts are resolved, Bob has a branch that's either rebased on
main or has the latest changes from
main merged into it, so it includes both the first feature Alice worked on and the feature Bob worked on. Now Bob can open a pull request that won't result in any conflicts.
The key to not get other people's config changes as uncommitted changes in your working directory is to apply the config every time you change branches. That means:
php craft project-config/apply
php craft migrate/all
By the way, you can usually skip step 3 with no problems. If you open a pull request without having pulled the latest changes from
main, Github will tell you if you can merge the PR without causing any conflicts. If Github reports no conflicts, you can just merge the PR which performs a three-way merge directly on the remote. If you do get conflicts, you can proceed to do step 3 (pull changes from main and merge/rebase).
And what's even worse, if person A did a pull request to main but wants to work on a different branch before that pull request gets merged, changing to another branch will also result in "pending changes"
You just need to use
php craft project-config/apply after switching branches, to make sure your development environment matches the state of the branch you're working on now.