Chapter 7 Common issues & tips
This section outlines some common issues you may run into, and how to fix them, as well as describing a few useful commands to make Git a little more user friendly.
7.1 Common issues and how to fix them
7.1.1 I’ve realised I made an error in my commit
If you’ve just committed some changes but realised a mistake in them you can “amend” the commit. However, this should be done before you push your changes! Things can get complicated if you try amending public commits.
To amend the commit, correct the file, add the file in Git and then use this command to combine the correction into the previous commit:
(Technically this combines both commits into a new commit that overwrites the last one).
If you’ve made a typo in your commit message you can also correct it with amend. Say your last commit looks like this:
109563e Some User | 2018/01/27 10:44 Added mew featuere
Adding the -m
flag to your amend allows you to add a new comment.
Your history will then look like this:
23237f1 Some User | 2018/01/27 10:44 Added new feature
7.1.2 I want to go back to an earlier commit
You’ve made some changes that didn’t work out for whatever reason, and now want to return your code to an earlier state. There are two ways to do this: reset and revert.
7.1.2.1 Reset
This option will “roll back” your directory to its earlier state, essentially going back in time and removing any changes since the commit you go back to.
Use
git reset --hard <commit-hash>
where <commit-hash>
is the unique hash of the commit you want to go back to (you can find this via git log
).
The --hard
option in this command means that your working directory and staging area will also be reset, which is usually what you want, but be careful as you will lose any uncommitted changes when you use this command.
7.1.2.2 Revert
This option keeps all the changes you have made, but adds an extra commit with new changes that reverse the previous changes.
You will usually want to use
git revert HEAD
to revert the most recent commit (which is what the HEAD
in this command refers to).
Reverting anything other than the most recent commit is not recommended.
If you want to revert multiple commits at once, you can use something of the form
git revert --no-commit HEAD~2^..HEAD
followed by
git commit -m "Reverted last three commits"
Walking through this:
The
--no-commit
part of the command means that the reversion will change the working directory and staged files, but not yet be committed. (You’ll have seen that we commit it afterwards, which is the usual way to work when reverting multiple commits at once).HEAD~2^
means the commit two commits beforeHEAD
(and e.g.HEAD~4^
would be the commit four commits beforeHEAD
)..
indicates to include all commits between the two specified
So the first command reverts the most recent commit and the two before it - three commits in all - but only makes those changes in the working directory and staging area rather than committing them. Then the second command is a standard commit command which commits them all with a message.
7.1.2.3 When should I use reset vs revert?
The two commands will result in a different git history. With reset
, any changes you roll back will not appear, giving a shorter history; with revert
, everything that happened will be recorded and the history will be longer. So if it’s not necessary for anyone to know about the rolled back changes, reset
is probably better; if you need a record of what happened then revert
is probably better.
There are a few other important considerations too:
You need to be a bit more careful when using
reset
, as it will erase any uncommitted changes and you’ll be unable to recover them.If any of the changes you want to reverse have been pushed to a remote server, you should use
revert
so that it’s clear to others that changes have been rolled back. Usingreset
on a shared history will create confusion because it will not be clear what has happened.You can’t (easily)
revert
past a merge because it’s unclear which merged branch you want to revert to.reset
is easier to use when the history you want to roll back includes a merge.
7.1.3 I’ve worked on the wrong branch (but haven’t committed yet)
You’ve made some changes to your code, saved them, but realised that you’ve been working on the wrong branch before committing. Fortunately, this is pretty easy to solve. The git stash command is your friend here: it allows you to store all your file changes away since the last commit away, and bring them back where you want - usually on a new branch.
The commands are: store away any changes with
(If you check git status
at this point you’ll see that your file changes since your last commit no longer appear.)
Then switch branch with
and use
to bring your changes back. That’s it!
Using the pop command does not commit your changes - you have simply moved uncommitted changes from one branch to another - and once you have “popped” your changes they will be removed from the stash.
Occasionally popping changes from the stash will cause a merge conflict. You can resolve this in the same way as a usual merge conflict by editing the files, and then add the result to your next commit. (Note that when a pop causes a merge conflict, your changes will not be removed from the stash like normal so you will still have access to them if needed.)
Using the stash
The git stash can technically hold many different sets of changes at once, but it is not good practice to store anything in the stash long-term. It is a temporary store and should only be used to quickly move changes around when needed.
7.1.4 I’ve worked on the wrong branch (and committed it)
If you’ve only realised that you’re working on the wrong branch after committing your code, then you’ll need to do two things. The first is to get the code onto the correct branch, and the second is to remove it from the wrong branch you committed it to.
If you forgot to create a new branch, you can create one now that includes the commits you want using
git branch <new_branch_name>
then roll back the current branch as described here.
If you already created a branch but forgot to switch to it, you’ll need to move the commits to the correct branch. You can do this by checking out the correct branch and copying the commits to it using cherry-pick:
git checkout <correct_branch>
git cherry-pick <commit-hash>
where <commit-hash>
is the commit you want to copy over. For multiple commits, you can copy them all over using
git cherry-pick <commit-hash-1>..<commit-hash-n>
where <commit-hash-1>
is the earliest commit you want to copy and <commit-hash-n>
is the most recent. Then check out the branch you accidentally committed them to and roll it back as described here.
7.2 Other tips
7.2.1 Log Customisation and Aliases
You can customise the log by adding extra arguments. For example, adding the --oneline
argument the log is cut down to one line per commit.
There are a lot of possible arguments to add to the log. This example will show the latest commit on each branch, give a rough branching diagram and put the date in a specified format.
git log --pretty=format:'%C(yellow)%h%Creset %an| %Cgreen%cd%Creset %s %C(cyan)%d' --graph --all --date=format:'%Y/%m/%d %H:%M'
All the possible arguments to add to git log
are in the documentation here.
Eventually you’ll have too many arguments to sensibly type, so you can use an alias. An alias allows you to define a new command based on an old command. You define one like this:
After this you can type
to carry out the command.
For example, using the long, customised log from above we can define a new command, “hist”.
git config --global alias.hist = log --pretty=format:'%C(yellow)%h%Creset %an| %Cgreen%cd%Creset %s %C(cyan)%d' --graph --all --date=format:'%Y/%m/%d %H:%M'
Allowing us to type:
to view a fancy version of the log, without having to type out a huge command!
7.3 Work Items
DevOps has rich project management functionality that can be used to manage projects of all sizes. At it’s most complex you can utilise a mix of Epics, Stories, Features, Tasks, Issues and User stories to manage your project.
These terms and planning stages for a project come from software development.
Instead we recommend treating features as the main type of work item and breaking your workload down into a number of features. This is similar to what you would do on GitHub with Issues.
With features you can again add lots of metadata but the most useful will be the following:
- Name
- Description
- Assigned to
There are then numerous ways to visualise work allocations across Azure DevOps ranging from individual task assignments to project boards (similar to trello boards).
By utilising work items you take out the need for tracking tasks manually.