Set git username and email:
$ git config --global user.name user2 $ git config --global user.email email@example.com
Set global log alias – this will allow
git glog to show summary, graphical, colour log history:
$ git config --global alias.glog "log --all --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
Create a feature branch using ticket number MTSU-1197 as the branch name
$ git checkout -b MTSU-1197 $ echo “this is a new file” > newfile $ git add newfile $ git commit -m “add newfile” $ git push origin MTSU-1197
Updating feature branch from the master branch
Merge Strategy method
Let’s look at a merge strategy first. We’ll simulate the master branch changing, and a new feature being incorporated before we can finish our feature.
$ git checkout -b master $ echo “some new feature” > somefile $ git add somefile $ git commit -m ‘add a new feature’
Now let’s make some other changes in our feature branch:
$ git checkout MTSU-1197 $ echo “more feature changes” >someotherfile $ git add someotherfile $ git commit -m ‘add more feature changes’
Now let’s try and pull the latest changes from the main ‘master’ branch into our feature:
$ git pull . master
Git will pull up a new editor that looks like the following:
Merge branch 'master' into MTSU-1197 # Please enter a commit message to explain why this merge is necessary, especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts the commit.
So what’s happened? In this case, Git has created a new ‘merge commit’ in our feature branch that ties the histories of these two branches together. This isn’t necessarily a bad thing – merging branches together is a non-destructive operation, so it retains the history of our changes made.
However, we might not want to many merge commits in our history. If our master branch is changing frequently, we’ll end up with lots of merge commits, which can make our history difficult to read.
Let’s reset our feature branch using a rebase – we’ll explain more about the
rebase tool in a second.
$ git rebase -i HEAD~2
You’ll see the following:
pick f4f3b23 add more feature changes pick a28c1d9 add a new feature # Rebase ff6e2f9..3e69fab onto ff6e2f9 (2 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # l, label = label current HEAD with a name # t, reset = reset HEAD to a label # m, merge [-C | -c ] [# ]
Let’s drop the second commit. Change:
pick f4f3b23 add more feature changes pick a28c1d9 add a new feature
pick f4f3b23 add more feature changes drop a28c1d9 add a new feature
And write the file and quit. You’ll now see that git has rebased your local repo:
Successfully rebased and updated refs/heads/MTSU-1197
Wait, what happened there? Effectively we rewrote Git history by dropping a commit out. We did this using a ‘rebase’ – we took the latest changes in the
master branch, and then replayed commits from our current branch on top. Git’s ‘interactive rebase’ (shown above) let’s us alter how this replay is performed. We can drop or squash commits, for example, when the current branch is replayed.
Rebasing results in a much cleaner project history, but can lead to pitfalls if notused correctly. While it’s normally safe to perform a ‘git pull –rebase’,
as we do below, when we start dropping and squashing commits there’s one
golden rule – don’t rebase a public branch. If someone else can see your code in a branch, then don’t drop, squash or amend commits, it’s safest to just leave it alone.
Now let’s use a rebase strategy to pull in the latest master branch changes. A
rebase involves moving our entire feature branch to begin on the tip of the main branch. Instead of creating a merge commit though, rebasing will create new commits for each commit in our feature branch, effectively rewriting history.
We’ve just reset our feature branch using our ‘interactive rebase’, so we can now rebase our new changes on the latest master branch.
Git pull . master --rebase From . * branch master -> FETCH_HEAD First, rewinding head to replay your work on top of it… Applying: add more feature changes
Awesome! Now we have the latest changes from the master branch, and our new code, and we haven’t produced an unnecessary merge commit.