One of the branching philosophies (section Developing Branching Strategy and Codeline Policy in Advanced SCM Branching Strategies - also read Perforce Best practices, its a pdf but goes into some other details) is that you branch on incompatabile policy.
A codeline policy
specifies the fair use
and permissible check-ins for the codeline,
and is the essential user’s manual for
codeline SCM. For example, the policy of
a development codeline should state that
it isn’t for release; likewise, the policy of a
release codeline should limit changes to
approved bug fixes. The
policy can also describe
how to document changes
being checked in, what
review is needed, what
testing is required, and
the expectations of
codeline stability after
check-ins. A policy is a
critical component for a
documented, enforceable
software development
process, and a codeline
without a policy, from an
SCM point of view, is out of control.
(from Perforce Best Practices)
Say you have the branches 'release' (or 'master') from which a release is built and 'trunk' (or 'dev') where developers check in working code. These are the policies of the branches. Noting the 'working code' is part of the 'dev' branch policy, one should never commit broken code to the dev branch. Often there are things such as CI servers hooked up to these branches and checking in broken code into dev could mess up everyone's branch and break the build.
However, there are times when it is appropriate to check in partial code that doesn't work. In these instances, one should branch - an incompatible policy with trunk. In this new branch, one can decide the policy ('broken code is ok') and then commit code to it.
There is one simple rule to determine if a
codeline should be branched: it should be
branched when its users need different
check-in policies. For example, a product
release group may need a check-in policy
that enforces rigorous testing, whereas a
development team may need a policy that
allows frequent check-ins of partially tested
changes. This policy divergence calls for a
codeline branch. When one development
group doesn’t wish to see another
(from Perforce Best Practices)
Realize that this is coming from a central server based SCM with a strong corporate mindset. The core idea is still good. These are often thought of implicitly - you don't check in untested dev code into the release branch. Thats a policy.
So branch, say that this branch can have broken code and commit away.
If I understood correctly, this is your situation:
,-c--c--c--c--M--a--a--X ← develop
o--o--y--y--y--y-´
After some common history (o), you committed and pushed your work (y). Your coworker (c) did work on his local repository and did a bad merge (M).
Afterwards there might be some additional commits (a) on top of M.
git reset --hard develop M^2
git branch coworker M^1
Now your graph looks exactly like before the bad merge:
,-c--c--c--c ← coworker
o--o--y--y--y--y ← develop
Do a good merge (G):
git checkout develop
git merge coworker
Resulting in:
,-c--c--c--c-、
o--o--y--y--y--y--G ← develop
Now transplant the additional commits:
git reset --hard X
git rebase --onto G M develop
This gives the final result:
,-c--c--c--c-、
o--o--y--y--y--y--G--a--a--X ← develop
Be aware that this might result in more merge conflicts. Also you just changed history, i.e. all your coworkers should clone/reset/rebase to the new history.
PS: of course you should replace G
, M
and X
in your commands by the corresponding commit id.
Best Answer
Making several small commits rather than one big one will not magically prevent conflicts, but it usually makes them less frequent and easier to deal with.
If you commit and push lots of small changes to master, then it's harder for conflicts to arise in the first place, since less code is changing between commits and the other developers will see some of your changes before they start to make their own.
If you have a feature branch that's broken up into lots of small commits when you merge, then the merge is done one commit at a time, so if there are a lot of conflicts, you only have to resolve one commit's worth of conflicts at a time, which is usually a lot easier than resolving them all at once.
The
git merge
command itself does not perform any commits, except for a single "merge commit" if necessary. It will not retroactively split an existing commit into several smaller commits or anything like that (I don't believe there's an easy way to do that in git, or any other VCS).