After initializing a repository, Git can help you with revision controlling files inside the working directory. However, it is not automatic. You need to tell Git which of your changes (aka revisions) should be committed to its memory for later use. Saving changes into Git's memory in that way is called committing and a change saved to the revision history is called a commit.
Here are the steps you can follow to learn how to create Git commits:
1. Do some changes to the content inside the working directory e.g., create a file named fruits.txt
in the things
directory and add some dummy text to it.
2. Observe how the file is detected by Git.
The file is shown as ‘unstaged’.
You can use the git status
command to check the status of the working directory.
$ git status
# On branch master
#
# No commits yet
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# a.txt
nothing added to commit but untracked files present (use "git add" to track)
3. Stage the changes to commit: Although Git has detected the file in the working directory, it will not do anything with the file unless you tell it to. Suppose you want to commit the current changes to the file. First, you should stage the file, which is how you tell Git which changes you want to include in the next commit.
When you stage a change, the change is moved to the staging area, which is a file Git uses to store information about what will go into your next commit. The staging area is also called the 'index' by the Git practitioners.
Select the fruits.txt
and click on the Stage Selected
button.
fruits.txt
should appear in the Staged files
panel now.
If Sourcetree shows a \ No newline at the end of the file
message below the staged lines (i.e., below the cherries
line in the above screenshot), that is because you did not hit enter after entering the last line of the file (hence, Git is not sure if that line is complete). To rectify, move the cursor to end of the last line in that file and hit enter (like you are adding a blank line below it). This new change will now appear as an 'unstaged' change. Stage it as well.
You can use the stage
or the add
command (they are synonyms, add
is the more popular choice) to stage files.
$ git add fruits.txt
$ git status
# On branch master
#
# No commits yet
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: fruits.txt
#
4. Commit the staged version of fruits.txt
.
Click the Commit
button, enter a commit message e.g. add fruits.txt
into the text box, and click Commit
.
Use the commit
command to commit. The -m
switch is used to specify the commit message.
$ git commit -m "Add fruits.txt"
You can use the log
command to see the commit history.
$ git log
commit 8fd30a6910efb28bb258cd01be93e481caeab846
Author: … < … @... >
Date: Wed Jul 5 16:06:28 2017 +0800
Add fruits.txt
Note the existence of something called the master
branch. Git uses a mechanism called 'branches' to facilitate evolving file content in parallel (we'll learn git branching in a later topic). Furthermore, Git auto-creates a branch named master
(or main
) on which the commits go on by default.
Expand the BRANCHES
menu and click on the master
to view the history graph, which contains only one node at the moment, representing the commit you just added. Also note a label master
attached to the commit.
This label points to the latest commit on the master
branch.
Run the git status
command and note how the output contains the phrase on branch master
.
5. Do a few more commits.
Make some changes to
fruits.txt
(e.g. add some text and delete some text). Stage the changes, and commit the changes using the same steps you followed before. You should end up with something like this.Next, add two more files
colors.txt
andshapes.txt
to the same working directory. Add a third commit to record the current state of the working directory.You can decide what to stage and what to leave unstaged. When staging changes to commit, you can leave some files unstaged, if you wish to not include them in the next commit. In fact, Git even allows some changes in a file to be staged, while other changes in the same file to be unstaged. This flexibility is particularly useful when you want to put all related changes into a commit while leaving out unrelated changes.
6. See the revision graph: Note how commits form a path-like structure aka the revision tree/graph. In the revision graph, each commit is shown as linked to its 'parent' commit (i.e., the commit before it).
To see the revision graph, click on the History
item (listed under the WORKSPACE
section) on the menu on the right edge of Sourcetree.
The gitk
command opens a rudimentary graphical view of the revision graph.
How to undo/delete a commit?
To undo the last commit, right-click on the commit just before it, and choose Reset current branch to this commit
.
In the next dialog, choose the mode Mixed - keep working copy but reset index
option. This will make the offending commit disappear but will keep the changes that you included in that commit intact.
If you use the Soft - ...
mode instead, the last commit will be undone as before, but the changes included in that commit will stay in the staging area.
To delete the last commit entirely (i.e., undo the commit and also discard the changes included in that commit), do as above but choose the Hard - ...
mode instead.
To undo/delete last n commits, right-click on the commit just before the last n commits, and do as above.
To undo the last commit, but keep the changes in the staging area, use the following command.
$ git reset --soft HEAD~1
To undo the last commit, and remove the changes from the staging area (but not discard the changes), used --mixed
instead of --soft
.
$ git reset --mixed HEAD~1
To delete the last commit entirely (i.e., undo the commit and also discard the changes included in that commit), do as above but use the --hard
flag instead (i.e., do a hard reset).
$ git reset --hard HEAD~1
To undo/delete last n commits: HEAD~1
is used to tell Git you are targeting the commit one position before the latest commit -- in this case the target commit is the one we want to reset to, not the one we want to undo (as the command used is reset
). To undo/delete two last commits, you can use HEAD~2
, and so on.