I'm the only one in my organization who's making commits with the following message:
Merge remote-tracking branch 'origin/develop' into develop
Not sure what I'm doing to cause them, but I'd like to stop.
What command am I issuing to create this commit, and what is the proper command I ought to be using to not produce it?
That should do it. Or if you want to continue to use pull
You can also setup that branch in your config to rebase automatically, or be setup like that automatically for any other future tracking branches you make. Then you can go back to just using
More on this in the "pull with rebase instead of merge" section of this page:
http://mislav.uniqpath.com/2010/07/git-tips/
git pull
is probably creating the commit. If you make a local commit and then rungit pull
after someone else pushes a commit up to the repository, Git downloads the other developer's commit and then merges it into your local branch.How to avoid these merge commits in the future
You could use
git pull --rebase
to prevent this from happening in the future, but rebasing has its perils, and I recommend avoidingpull
altogether.Instead, I encourage you to follow this usage pattern:
Explanation
git remote update -p
downloads all of the commits in the remote repositories and updates the remote tracking branches (e.g.,origin/master
). It does NOT touch your working directory, index, or local branches.The
-p
argument prunes deleted upstream branches. Thus, if thefoo
branch is deleted in theorigin
repository,git remote update -p
will automatically delete yourorigin/foo
ref.git merge --ff-only @{u}
tells Git to merge the upstream branch (the@{u}
argument) into your local branch but only if your local branch can be "fast forwarded" to the upstream branch (in other words, if it hasn't diverged).git rebase -p @{u}
effectively moves the commits you've made but haven't yet pushed on top of the upstream branch, which eliminates the need to create the silly merge commits you're trying to avoid. This improves the linearity of the development history, making it easier to review.The
-p
option tells Git to preserve merges. This prevents Git from linearizing the commits being rebased. This is important if, for example, you merged a feature branch intomaster
. Without-p
, every commit on the feature branch would be duplicated onmaster
as part of the linearization done bygit rebase
. This would make the development history harder to review, not easier.Beware:
git rebase
might not do what you expect it to do, so review the results before pushing. For example:I prefer this approach over
git pull --rebase
for the following reasons:-p
(--preserve-merges
) option togit rebase
in case you need to rebase an intentional merge (e.g., merge of an already-pushed feature branch intomaster
).Shorthand:
git up
instead ofgit pull
To make it easy to do the above, I recommend creating an alias called
up
:Now all you need to do to bring your branch up to date is to run:
instead of
git pull
. If you get an error because your local branch has diverged from the upstream branch, that's your cue to rebase.Why not
git pull --rebase
?Running
git pull --rebase
is equivalent to runninggit fetch
followed bygit rebase
. This attempts to fast-forward to the new upstream commits, but if that's not possible then it will rebase your local commits onto the new upstream commits. This is usually OK, but be careful:git pull --rebase
does not give you an opportunity to examine the commits before incorporating them. Depending on what changed upstream, it's quite possible that rebase is the wrong operation—arebase --onto
,merge
,reset
, orpush -f
might be more appropriate than a plainrebase
.--preserve-merges
to the rebase operation, so any intentional merge of a feature branch will be linearized, replaying (and thus duplicating) all of the feature branch commits."Fixing" an existing merge commit created by
git pull
If you haven't yet pushed a merge commit created by
git pull
, you can rebase out the merge commit. Assuming you haven't made any intentional merges (e.g., merging an already-pushed feature branch into your current branch), the following should do it:The above command tells Git to select all of the non-merge commits reachable from
HEAD
(the current commit), minus all the commits reachable from@{u}
(which is shorthand for "the upstream branch", i.e.,origin/master
ifHEAD
ismaster
), replay (cherry-pick) them on top of the upstream branch, and then move the current branch reference to point to the result of replaying the commits. This effectively moves the non-merge commits onto the most recent upstream commit, which eliminates the merge created bygit pull
.If you have an intentional merge commit, you don't want to run
git rebase @{u}
because it will replay everything from the other branch. Dealing with this case is substantially more complicated, which is why it's good to usegit up
and avoidgit pull
altogether. You'll probably have to usereset
to undo the merge created bypull
and then dogit rebase -p @{u}
. The-p
argument togit rebase
hasn't worked reliably for me, so you might end up having to usereset
to undo the intentional merge, update your local branch to@{u}
, and then redo the intentional merge (which is a pain if there were a lot of hairy merge conflicts).