Snapshotting

Introduction To Git Snapshots

We learned earlier that Git uses the snapshot method which will capture the situation and conditions of the repository when we save changes using Git commands.

With the snapshot method, Git will only save changes that occur in both files and folders into snapshot at that time. Meanwhile, files and folders that have not changed will be saved as references to the previous snapshot.

Let’s learn together how a Git snapshot is created:

Note: Before running the Git command below, make sure it is in the Git repository, if not, then use the git init command first.

File stages in Git

Working, staging and commit

Working, staging and commit (Source: axosoft.com)

The files in a Git repository will exist in three different stages:

  • Not staged: The folder we are working on now is called the working directory. When we create or change a file in the working directory, the file is not staged. When we work on a task, there will be files that we change or that we leave as is. Now for the file that we changed, to save it into Git, we need to move it to the staging area.
  • Staged: The staged process will select which file we want to ‘commit’ later. When the files have been collected, we can save them and move them to the committed stage with the git commit command.
  • Committed: The series of commits becomes the history of our project from start to finish, each commit can be seen in the git log and with it we can see the entire history of our project from the start of our git repository.

Commands to check current repository status and history

The Git commands that are very useful for viewing the status of the repository that we are working on and often use are:

  • git status: displays the state of the working directory and staging area so we can see which files are not staged and which are staged. More details here

  • git log: displays committed commits. More details here

To see Git Snapshot in practice, watch the following video:

Introduction Github Snapshot

Introduction Github Snapshot

Add

Git add visualization

Git add visualization (Source: img-bc.icode.best)

The git add command functions to add new files or changed files in the working directory to the staging area

How to Use git add

Common usage and options for git add

  • git add <file>: Adds the specified file shell > git add file1.txt

  • git add .: Adds all files shell > git add .

We can see the other git add options with tldr git add or git add -h

The safest way to use git add is to designate a specific file or directory that we want to add to the staging area. Example:

  • git add login/: Adds all changes to files inside folder login
  • git add README.md: Adds all changes to the README.md file

git add All Files

If we want to add to the staging area all files, there are several commands that can be used, namely:

Command New Files Modified Files Deleted Files Description
git add . ✔️ ✔️ ✔️ Adds all files recursively in the current folder
git add -u ✔️ ✔️ Adds all files that have previously been tracked in Git.

Source: stackoverflow.com

Saving all files to the staging area has several risks, namely:

  • Creating a commit that is too large may contain changes that have nothing to do with what is being done.
  • There may be files containing sensitive information that we accidentally committed such as password, token, etc.

We can prevent the possibility of the 2 points above by ensuring that each commit only contains related changes and match the description of its commit.

Undo Added Files

For example, we have files hello.txt and world.txt in repository and we have added both to the staging area

> git status
On branch main

No commits yet

Changes to be committed:
   (use "git rm --cached <file>..." to unstage)
         new file: hello.txt
         new file: world.txt

Then we do the git reset command on file hello.txt to return it to working directory

> git reset hello.txt
> git status
On branch main

No commits yet

Changes to be committed:
   (use "git rm --cached <file>..." to unstage)
         new file: world.txt

Untracked files:
   (use "git add <file>..." to include in what will be committed)
         hello.txt

So we can see that the file hello.txt has moved to the working directory. If we do git commit, only world.txt will be committed. In this way, we can ensure that the files that are committed are only the files that we want.

Commit

Git Commit Flow

Git Commit Flow (Source: cspsprotocol.com)

How to use git commit

The git commit command functions to save and move files in the staging area to the committed stage.

When saving we are required to provide a commit message which contains a record of the changes that occurred in the file or collection of files that we committed.

Commit Message Best Practice

Commit message must be short and describe the changes made. Why should so? Because when looking at the history of the project, we will be guided by the commit message, so that the commit message ideally tells a story from the beginning of the history of our project to the end.

The Commit message must be in present tense and explain clearly & concisely the changes made. We can also add semantic commit message so that each commit message has its own category (feat: feature, fix: fix, docs: addition of document) as in the following example :

  • git commit -m "feat: create file structure for Git guides"
  • git commit -m "fix: translate Git cheat sheet into German"
  • git commit -m "docs: update broken URL to Git resources"

By ensuring our commit message can be read easily, we’ll be able to rollback (restore the status of our project) to any commit.

Checkout

The git checkout command is a command that is often used, one of which is to move between commits so that we can review the contents of a particular commit.

Let’s say we have a repository that has several commits and we do a checkout to one of the commits.

With the command git log --oneline it will display commit per line and have a short output in the form of the first seven characters of the commit id (example: 7ba2a60) and commit message. Use the commit id to switch commit:

Graph commit 1
> git log --oneline
c21091a6 (HEAD -> master) docs: add note to snapshot and git add
e2eea3ae docs: add ideation
> git checkout e2eea3ae
> git log --oneline
d82c536 (HEAD) docs: add ideation

Graph commit 2

So it can be seen that by doing checkout we can move to commit with id d82c536. If we want to get back to work after seeing the contents of this commit, we can run the command: git checkout -

> git checkout -
> git log --oneline
7ba2a60 (HEAD -> master) docs: add note to snapshot and git add
d82c536 docs: add ideation

Graph commit 1

So, it can be seen that commit has moved to the previous position.

How To Undo A Commit With git revert

git revert is the highly recommended and safest way to undo a commit.

> git log --oneline
47d87b4 (HEAD -> master) docs: minor typo fix
c21091a docs: add note to snapshot and git add
e2eea3a docs: add ideation

For example, if we want to undo commit “docs: add note to snapshot and git add”, we can do the following command:

> git revert c21091a

git revert will create a new commit whose contents are the opposite (inverse) of the commit we want to undo. If we call git log again:

> git log --oneline
562560e (HEAD -> master) Revert "docs: add note to snapshot and git add"
47d87b4 docs: minor typo fix
c21091a docs: add note to snapshot and git add
e2eea3a docs: add ideation

Graph commit 3

Then git revert will become a new commit which will undo all the changes we have made previously:

  • If we have added files, git revert will remove them
  • If we make changes to a file the changes will be cancelled
  • If we delete a file, git revert will add it back.

Git revert

Git revert (Source: cloudinary.com)

Updating Commits With Git Commit Amend

For example, we have done a commit and we realize that there was an error in the commit (whether we forgot to edit a few lines of the file or gave the wrong commit message) we can do git commit --amend, where the entire file is staging will now be put in the previous commit.

Warning: do not do git commit --amend if the previous commit has already been push

git rm

There are 2 ways to use git rm:

  • Used to delete files from the staging area and working directory
  • Used to cancel (delete) file from staging area back to working directory. You could say this is the opposite of the git add command.

Here we will focus on the second use, namely canceling the file from the staging area back to the working directory. For that we will use git rm --cached.

How to use git rm for staged files

We use the git rm --cached command to move a file from staging to working directory. For example, we have a file named hello.txt which is already in the staging area.

[user@localhost]$ git status
On branchmaster
No commits yet
Changes to be committed:
   (use "git rm --cached <file>..." to unstage)
         new file: hello.txt

So we can move file hello.txt from staging area to working directory without deleting it from file system by:

[user@localhost]$ git rm hello.txt --cached
rm 'hello.txt'
[user@localhost]$ git status
On branch main
No commits yet
Untracked files:
   (use "git add <file>..." to include in what will be committed)
         hello.txt
nothing added to commit but untracked files present (use "git add" to track)

So it can be seen that the file hello.txt is no longer in the staging area but has moved to the working directory.

Note: Remember to use the --cached option. Without the --cached option, the file will be deleted from the staging area and working directory.

git diff

What is git diff?

git diff is used to inspect changes we make when working on a Git repository. The way it works is to compare the file in the working directory with the file in the commit in the repository.

Examples

We add a file in the initialized repository to try git diff

> touch diff_test.txt
> echo "this is a git diff test example" > diff_test.txt
> git add diff_test.txt
> git commit -am "add diff test file"
[main (root-commit) 6f77fc3] add diff test file
1 file changed, 1 insertion(+)
create mode 100644 diff_test.txt

For example, now we change all the contents of the file diff_test.txt.

> echo "this is a diff example" > diff_test.txt

By executing git diff, we will compare the changes just committed (changing the contents of file diff_test.txt) with the previous commit, which will produce the following output:

> git diff
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a different example

The following is an explanation of the output above:

  1. Comparison input

    diff --git a/diff_test.txt b/diff_test.txt

    a/diff_test.txt is the file in the commit that we are comparing with the file in the working directory, which is written here as b/diff_test.txt.

  2. Markers for changes

    --- a/diff_test.txt
    +++ b/diff_test.txt

    These lines are the symbols assigned to each input source. Changes from a/diff_test.txt are marked with the symbol --- and changes from b/diff_test.txt are marked with the symbol +++.

  3. Diff content

    -this is a git diff test example
    +this is a different example
    • The - sign indicates that this line is deleted and does not exist in the file currently in the working directory.
    • The + sign indicates that this line was added in the current file and is not present in the file we committed to the repository.

    If the - sign and the + sign are close together, this usually indicates that a replacement has occurred in that line. In the example above, the line this is a git diff test example is replaced with this is a diff example. And that’s what we do in this example.

Back to top