Back in March, I wrote about pushing and pulling as an introduction to getting data from a remote Git server. Now that we've talked about rebasing (twice), we can talk about the different pull strategies.
git fetch merely makes the changes available in your local repository; it doesn't affect the branch(es) that you are on. On the other hand,
git pull does affect the branches that you are on as it tries to include changes from upstream.
By default, Git will attempt to do a merge whenever you pull changes. Here's what it looks like when you do a merge:
$ git log --oneline master e1c1744 Third 36c3a20 Second c66b73b First # Take a branch from a previous point in history $ git checkout -b feature-merge 36c3a20 Switched to a new branch 'feature-merge' # Set it up so I can pull from master $ git branch --set-upstream feature-merge master Branch feature-merge set up to track local branch master. $ git log --oneline feature-merge 36c3a20 Second c66b73b First # Add another file so we diverge $ touch feature-merge.txt $ git add feature-merge.txt $ git commit -m "Feature-Merge" [feature-merge a16a3db] Feature-Merge 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 feature-merge.txt # Now, let's see what happens when we pull $ git pull From . * branch master -> FETCH_HEAD Merge made by recursive. 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 c $ git log --oneline --graph * 23b50a0 Merge branch 'master' into feature-merge |\ | * e1c1744 Third * | a16a3db Feature-Merge |/ * 36c3a20 Second * c66b73b First
Here, we've invoked the default operation which is to do a merge. When we're behind
master with local changes, and we do a pull, it automatically sets up a merge node, as shown by the graph above. (Normally the branch would be a remote one; however, I'm showing a tracked local branch for convenience.)
However, this is configurable to do a rebase instead. This configuration is done on a branch-by-branch basis. Let's create a new branch to experiment with this feature:
$ git checkout -b feature-rebase 36c3a20 Switched to a new branch 'feature-rebase' $ git branch --set-upstream feature-rebase master Branch feature-rebase set up to track local branch master. $ git log --oneline feature-rebase 36c3a20 Second c66b73b First # Add another file so we diverge $ touch feature-rebase.txt $ git add feature-rebase.txt $ git commit -m "Feature-Rebase" [feature-rebase 62855ee] Feature-Rebase 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 feature-rebase.txt $ git log --oneline 62855ee Feature-Rebase 36c3a20 Second c66b73b First # Configure the branch for rebase operations $ git config branch.feature-rebase.rebase true # Now, let's see what happens when we pull $ git pull From . * branch master -> FETCH_HEAD First, rewinding head to replay your work on top of it... Applying: Feature-Rebase $ git log --oneline * ff0ecc2 Feature-Rebase * e1c1744 Third * 36c3a20 Second * c66b73b First
What's happened here is that instead of creating a merge node, the pull operation resulted in a rebase of the underlying branch against the current master. This is dangerous (in the sense that a rebase is dangerous and changes history) but provided that you're doing this on local branches (those not pushed to the repository yet) then you may find this acceptable.
This configuration has to be done on a branch-by-branch basis. If your preferred way of working is to always enable this option, then there is a configuration item which can help:
$ git config branch.autosetuprebase always
If this is configured (either in a repository or globally with the
--global setting) then whenever you create a new branch, it will automatically add
branch.name.rebase=true for you.
Come back next week for another instalment in the Git Tip of the Week series.