Learn how to undo changes in Git using Bitbucket Cloud
Objective
Learn how to undo changes on your local machine and a Bitbucket Cloud repository while collaborating with others.
Mission Brief
Commands covered in this tutorial:
- git revert, git reset, git log, an git status
Time
40 minutes
Audience
This tutorial assumes familiarity with git commands:git clone
, git commit
, git pull
, and git push
Everyone makes mistakes. Not every push is perfect so this tutorial will help you use the most common git functions to undo a change or changes safely.
This tutorial assumes familiarity with the following git commands:
If you don't know those commands we can help you Learn git with Bitbucket Cloud. Then come back here and learn how to undo changes. These git
commands are applicable to a windows or unix environment. This tutorial will utilize unix command line utilities when instructing file system navigation.
Undoing changes on your local machine
When the change you want to undo is on your local system and hasn't been pushed to a remote repository there are two primary ways to undo your change:
Command | Definition |
---|---|
| Definition An 'undo' command, though not a traditional undo operation. Instead of removing the commit, it figures out how to invert the changes in the commit, then appends a new commit with the inverse content. This prevents Git from losing history, which is important for the integrity of your revision history and for reliable collaboration. |
| Definition
A versatile
For a complete description of how |
SEE SOLUTION
Advanced Git tutorials
related material
Git commands
As you progress through the tutorial you'll learn several other git commands as part of learning how to undo changes, so let's get started.
Fork a repository
Let's begin by creating a unique repository with all the code from the original. This process is called “forking a repository”. Forking is an extended git
process that is enabled when a shared repository is hosted with a 3rd party hosting service like Bitbucket.
1. Click or enter the following URL: https://bitbucket.org/atlassian/tutorial-documentation-tests/commits/all
2. Click the + symbol on the left sidebar, then select Fork this repository, review the dialog and click Fork repository.
3. You should be taken to the overview of the new repository.
4. Click the + symbol and select Clone this repository.
5. On your computer clone the repository.
6. Navigate to the directory containing the cloned repository.
Now that you've got a repository full of code and an existing history on your local system you're ready to begin undoing some changes.
Find changes on your local system
You'll have to be able to find and reference the change you want to undo. This can be accomplished by browsing the commit UI on Bitbucket and there are a few command line utilities that can locate a specific change.
git status
You'll have to be able to find and reference the change you want to undo. This can be accomplished by browsing the commit UI on Bitbucket and there are a few command line utilities that can locate a specific change.
$ git status
On branch main
Your branch is up-to-date with 'origin/main'.
nothing to commit, working tree clean
The output of git status
here shows us that everything is up-to-date with the remote main branch and there are no pending changes waiting to be committed. In the next example we will make some edits to the repository and examine it in a pending changes state. This means you have changes to files in the repository on your local system that you haven't prepared (or staged) to be added to the project history.
To demonstrate this next example, first open the myquote2.html
file. Make some modifications to the contents of myquote2.html
, save and exit the file. Let us once again execute git status
to examine the repository in this state.
$ git status
On branch main
Your branch is up-to-date with 'origin/main'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
Modified: myquote2.html
no changes added to commit (use "git add" and/or "git commit -a")
--
The output here shows that the repository has pending modifications to myquote2.html
. Good news! If the change you want to undo has, like the example above, not been added to the staging area yet you can just edit the file and keep going. Git only starts tracking a change when you add it to the staging area and then commit it to the project history.
Let us now “undo” the changes we have made to myquote2.html
. Because this is a simplified example with minimal changes, we have two available methods for undoing the changes. If we execute git checkout myquote2.html
The repository will restore myquote2.html
to the previously committed version. Alternatively, we can execute git reset --hard
which will revert the whole repository to the last commit.
git log
The git log
command lets you list the project history, filter it, and search for specific changes. While git status
lets you inspect the working directory and the staging area, git log
only shows the committed history.
The same log of commited history can be found within the Bitbucket UI by accessing the “commits” view of a repository. The commits view for our demo repository can be found at: https://bitbucket.org/dans9190/tutorial-documentation-tests/commits/all. This view will have a similar output to the git log
command line utility. It can be used to find and identify a commit to undo.
In the following example you can see several things in the history but each change is, at its root, a commit so that's what we'll need to find and undo.
$ git status
On branch main
Your branch is up-to-date with 'origin/main'.
nothing to commit, working tree clean
$ git log
commit 1f08a70e28d84d5034a8076db9103f22ec2e982c
Author: Daniel Stevens <dstevens@atlassian.com>
Date: Wed Feb 7 17:06:50 2018 +0000
Initial Bitbucket Pipelines configuration
commit 52f823ca251a132225dd1cc18ad768de8d336e84
Author: Daniel Stevens <dstevens@atlassian.com>
Date: Fri Sep 30 15:50:58 2016 -0700
repeated quote to show how a change moves through the process
commit 4801b87c2147dce83f1bf31acfcffa6cb1d7e0a5
Merge: 1a6a403 3b29606
Author: Dan Stevens [Atlassian] <dstevens@atlassian.com>
Date: Fri Jul 29 18:45:34 2016 +0000
Merged in changes (pull request #6)
Changes
Let's look a little closer at one of the commits in the list:
commit 52f823ca251a132225dd1cc18ad768de8d336e84
Author: Daniel Stevens <dstevens@atlassian.com>
Date: Fri Sep 30 15:50:58 2016 -0700
repeated quote to show how a change moves through the process
What you can see is each commit message has four elements:
Element | Description |
---|---|
Commit hash | Description An alphanumeric string (SHA-1 encoded) that identifies this specific change |
Author | Description The person who committed the change |
Date | Description The date the change was committed to the project |
Commit message | Description A text string that describes the change(s). Best practice tip: write short descriptive commit messages and you'll help create a more harmonious working repository for everyone. |
Locate a specific commit
Most likely the change you want to undo will be somewhere further back in the project history which can be quite extensive. So let's learn a couple basic operations using git log
to find a specific change.
1. Go to your terminal window and navigate to the top level of your local repository using the cd
(change directory) command.
$ cd ~/repos/tutorial-documentation-tests/
Enter the git log --oneline
command. Adding --oneline
will display each commit on a single line that allows you to see more history in your terminal.
Press the q key to exit the commit log and return to your command prompt at any time.
You should see something like the following example:
$ git log --oneline
1f08a70 (HEAD -> main, origin/main, origin/HEAD) Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 (origin/changes) myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
...
2. Press the q key to return to your command prompt.
3. Locate the commit with the hash c5826da
and more changes in the list the git log
command produced. Someone didn't write a descriptive commit message so we'll have to figure out if that's got the changes we need.
4. Highlight and copy the commit hash c5826da
from the git log
result in your terminal window.
5. Type git show
then paste or transcribe the commit hash you copied and press enter. You should see something like this:
$git show c5826daeb6ee3fd89e63ce35fc9f3594fe243605
commit c5826daeb6ee3fd89e63ce35fc9f3594fe243605
Author: Daniel Stevens <dstevens@atlassian.com>
Date: Tue Sep 8 13:50:23 2015 -0700
more changes
diff --git a/README.md b/README.md
index bdaee88..6bb2629 100644
--- a/README.md
+++ b/README.md
@@ -11,12 +11,7 @@ This README would normally document whatever steps are necessary to get your app
### How do I get set up? ###
* Summary of set up
-* Configuration
-* Dependencies
-* Database configuration
-* How to run tests
-* Deployment instructions
-* more stuff and things
:
The prompt at the bottom will continue to fill in until it shows the entire change. Press q to exit to your command prompt.
Filter the git log to find a specific commit
This filter | Does this | This example command | Would result in |
---|---|---|---|
| Does this Limits the number of commits shown | This example command | Would result in The 10 most recent commits in the history |
| Does this Limits the commits shown to the correlating time frameYou can also use | This example command | Would result in All commits after July 4, 2017 |
| Does this Lists all commits whose author matches the name | This example command | Would result in All commits made by any author with Alana in the name field |
| Does this Returns any commit with a commit message which matches the string you entered | This example command | Would result in All commits with HOT- as a text string in their messages |
This was a very brief look at the git log
command if you like working in the command like you'll probably want to check out the advanced git log tutorial.
Undo a change with git reset
To get started let's just undo the latest commit in the history. In this case let's say you just enabled Bitbucket's CI/CD solution pipelines but realized the script isn't quite right.
1. Enter git log --oneline
in your terminal window.
2. Copy the commit hash for the second commit in the log: 52f823c
then press q to exit the log.
3. Enter git reset --soft 52f823c
in your terminal window. The command should run in the background if successful. That's it, you've undone your first change. Now let's see the result of this action.
4. Enter git status
in your terminal window and you will see the commit was undone and is now an uncommitted change. It should look something like this:
$ git status
On branch main
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: bitbucket-pipelines.yml
5. Enter git log --oneline
in your terminal window. You should see something like this:
$ git log --oneline
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 (origin/changes) myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
6. You can see the new HEAD
of the branch is commit 52f823c
which is exactly what you wanted.
7. Press q to exit the log. Leave your terminal open because now that you've learned how to do a simple reset, let's try something a little more complex.
Undo several changes with git reset
To get started let's just undo the latest commit in the history. In this case let's say you just enabled Bitbucket's CI/CD solution pipelines but realized the script isn't quite right.
1. Enter git log --online
2. Copy the commit hash 1a6a403
(myquote edited online with Bitbucket) which is the commit just below pull request #6 which has the changes we want to undo.
3. Enter git reset 1a6a403
in your terminal window. The output should look something like this:
$ git reset 1a6a403
Unstaged changes after reset:
M README.md
M myquote2.html
You can see that the changes are now in an uncommitted state. This means that now we've removed several changes from both the history of the project and the staging area.
4. Enter git status
in your terminal window. The output should look something like this:
$ git status
On branch main
Your branch is behind 'origin/main' by 6 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
modified: myquote2.html
Untracked files:
(use "git add <file>..." to include in what will be committed)
bitbucket-pipelines.yml
no changes added to commit (use "git add" and/or "git commit -a")
Now you can see that the first change we undid (the bitbucket-pipelines.yml
file) is now completely untracked by git
. This is because invoking git reset
removes the change from both the head of the branch and the tracking or index area of git
. The underlying process is a bit more complex than we can cover here, you can read more in git reset
.
5. Enter git log --oneline
in your terminal window.
1a6a403 myquote edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
e52470d README.md edited online with Bitbucket
e2fad94 README.md edited online with Bitbucket
592f84f Merge branch 'main' into new-feature2 Merge branch especially if it merges an updated upstream into a topic branch.
7d0bab8 added a line
879f965 adding to the quote file
8994332 Merged in HOT-235 (pull request #2)
b4a0b43 removed sarcastic remarks because they violate policy.
b5f5199 myquote2.html created online with Bitbucket
b851618 adding my first file
5b43509 writing and using tests
The log output now shows the commit history has also been modified and begins at commit 1a6a403. For the sake of demonstration and further example, let’s say we want to now undo the reset we just did. After further consideration, maybe we wanted to keep the contents of pull request #6.
Pushing resets to Bitbucket
Git resets
are one of a few “undo” methods git
offers. Resets are generally considered an ‘unsafe’ option for undoing changes. Resets are fine when working locally on isolated code but become risky when shared with team members.
In order to share a branch that has been reset with a remote team a ‘forced push’ has to be executed. A ‘forced push’ is initiated by executing git push -f
. A forced push will destroy any history on the branch that was built after the point of the push.
An example of this ‘unsafe’ scenario is as follows:
- Dev A has been working on a branch developing a new feature.
- Dev B has been working on the same branch developing a separate feature.
- Dev B decides to reset the branch to an earlier state before both Dev A and Dev B started work.
- Dev B then force pushes the reset branch to the remote repository.
- Dev A pulls the branch to receive any updates. During this pull Dev A receives the forced update. This resets Dev A’s local branch back in time before any of their feature work was done and loses their commits.
Undo a git reset
So far we have been passing git commit
Sha hashes to git reset
. The git log
output is now missing commits that we have reset. How will we get those commits back? Git never fully deletes a commit unless it has become detached from any pointers to it. Furthermore git stores a separate log of all ref movement called “the reflog”. We can examine the reflog by executing git reflog
.
1a6a403 HEAD@{0}: reset: moving to 1a6a403
1f08a70 HEAD@{1}: reset: moving to origin/main
1f08a70 HEAD@{2}: clone: from git@bitbucket.org:dans9190/tutorial-documentation-tests.git
Your output from git reflog
should be similar to the above. You can see a history of actions on the repo. The top line is a reference to the reset we did to reset pull request #6. Let us now reset the reset to restore pull request #6. The second column of this reflog output indicates a ref pointer to a modification action take on the repo. Here HEAD@{0}
is a reference to the reset command we previously executed. We do not want to replay that reset command so we will restore the repo to HEAD@{1}.
$ git reset --hard HEAD@{1}
HEAD is now at 1f08a70 Initial Bitbucket Pipelines configuration
Let us now examine the repos commit history with git log --oneline
:
$git log --online
1f08a70 Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
e52470d README.md edited online with Bitbucket
e2fad94 README.md edited online with Bitbucket
592f84f Merge branch 'main' into new-feature2 Merge branch especially if it merges an updated upstream into a topic branch.
7d0bab8 added a line
:
The log output now shows the commit history has also been modified and begins at commit 1a6a403. For the sake of demonstration and further example, let’s say we want to now undo the reset we just did. After further consideration, maybe we wanted to keep the contents of pull request #6.
git revert
The previous set of examples did some serious time traveling to undo operations using git reset
and git reflog
. Git contains another ‘undo’ utility which is often considered ‘safer’ than reseting. Reverting creates new commits which contain an inverse of the specified commits changes. These revert commits can then be safely pushed to remote repositories to share with other developers.
The following section will demonstrate git revert
usage. Let us continue with our example from the previous section. To start let us examine the log and find a commit to revert.
$ git log --online
1f08a70 Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
1f08a70 Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
e52470d README.md edited online with Bitbucket
e2fad94 README.md edited online with Bitbucket
592f84f Merge branch 'main' into new-feature2 Merge branch especially if it merges an updated upstream into a topic branch.
7d0bab8 added a line
:
For this example let’s pick the most recent commit 1f08a70
as our commit to operate on. For this scenario let's say that we want to undo the edits made in that commit. Execute:
$ git revert 1f08a70
This will kick off a git merge
workflow. Git will create a new commit thats content is a reverse of the commit that was specified for the revert. Git will then open up a configured text editor to prompt for a new commit message. Reverts are considered the safer undo option because of this commit workflow. The creation of revert commits leave a clear trail in the commit history of when an undo operation was executed.
You just learned how to undo changes!
Congratulations, you’re done! Come back to this tutorial any time or head to the Undoing Changes section to go more in depth. Keep up the good work in Bitbucket!
Share this article
Next Topic
Recommended reading
Bookmark these resources to learn about types of DevOps teams, or for ongoing updates about DevOps at Atlassian.