In the following, I don't mention use of pull
; as you note, it is basically fetch
followed by merge
(unless configured to be something different), so you can substitute it as appropriate.
Probably the simplest workflow for two people sharing a branch is commit
, fetch
, merge
, push
. It's probably fine to treat that as the default, recognizing the reasons why you would do something different:
First, this does assume you've reached a state locally where you would want to create a permanent commit point. What criteria you have for that would be a discussion for your team, but basically you're just saying it's a point you should be able to return to in the future. You probably don't want to clutter your history with a bunch of partially-completed changes, and for debugging purposes some teams say that every permanent commit should pass automated tests.
This is important because if you're at a commit O
, you have local changes which you commit as L
, and then fetch and merge remote commit R
, you end up with something like
O -- L -- M <--(master)
\ /
-- R --
Now L
is basically locked into your history (especially after a subsequent push
). So for example, if you then make some more local changes and commit them giving
O -- L -- M -- L2 <--(master)
\ /
-- R --
there is not a straightforward way to squash L
and L2
together.
The simplest way to address this is to stash
your local changes instead of committing them if they are not ready to be committed. When you pop (or apply) the stash, you'd still have to resolve any conflicts. The result would be
O -- R <--(master)
with uncommitted (and possibly unstaged, depending on how you handle the stash) changes.
Another common variation is to rebase
local changes on top of the newly-fetched commits. This can make the history look simpler (doing away with commits to merge local changes with remote ones), and since it keeps your local changes at the tip it makes it easier to amend them (as long as you haven't pushed them). But, it also creates commit states that haven't really passed whatever automated tests you might have, so could run afoul if you want a 'clean commit' policy as suggested above.