Git Synthesis

A Comprehensive Guide to Git Commands and Best Practices

Subfolder

Glossary git
git best pratice
How to write a commit message
git commit –amend
uncommit

Introduction

Git is a powerful distributed version control system that enables teams to collaborate on software development projects. It provides a way to track changes made to the codebase, manage different versions, and work collaboratively with others. This guide aims to provide you with comprehensive knowledge of Git commands and best practices.

File Status

In Git, a file can have two statuses, untracked or tracked. If a file is tracked, it can be in one of three states: unchanged, staged, or unstaged. To check the status of a file, use the following command:

1
$ git status
  • untracked: the file has not been added to Git yet.
  • tracked: the file has been added to Git.
    • unchanged (not show): there are no changes to the file.
    • staged: the file has been marked for inclusion in the next commit.
    • unstaged: the file has been modified, but the changes have not been marked for inclusion in the next commit.

Commit

Preparing for a commit

Before making a commit, it’s important to verify the changes made to the file(s). The following commands can be used to prepare for a commit:

1
2
3
4
5
6
$ git status # show the working tree status
$ git diff <file>   # verify changes in file
$ git add <file>    # add a file to commit (staged)
$ git add -p <file> # choose a specific part of a file to stage
$ git rm <file>     # remove indexed file
$ git reset HEAD <file> # remove a file from stage (unstaged)

To see/ recheck all staged files (green) before committing, use the following command:

1
$ git status

To commit the changes with a message, use the following command:

1
$ git commit -m "<msg>"

For more information on how to write a commit message, check out How to Write a Git Commit Message

Append changes to the last commit

To append/ modify changes to the last commit, check out git commit –amend

Unstaged

If a file has been added to the staging area but needs to be removed, use the following commands:

1
2
3
4
5
$ git add <file>
$ git diff <file>       # verify that there are no changes
$ git reset HEAD <file> # remove the file from the staging area (unstaged)
$ git reset --hard origin/master # discard any changes to the file
$ git diff <file>       # verify that the changes have been removed

Uncommit

To undo a commit, check out Uncommit

Push

When pushing changes to a remote repository, it’s important to push changes by job, task, or feature, rather than by time. This ensures that the changes are organized and easy to track.

Preparing for a push

Before pushing changes to a remote repository, it’s important to check the local commits that haven’t been pushed yet. Use the following commands to check the unpushed local commits:

1
2
$ git log origin/master..HEAD  # show all local commits (unpushed)
$ git diff origin/master..HEAD # show the differences between local and remote

To push the changes to the remote repository, use the following command:

1
git push -u <remote-name> <branch>

Pull request

To create a pull request, you must first fork the repository, make changes on your branch and push the changes.

1
2
3
4
5
6
7
$ git clone <git-repos>

$ git checkout -b <branch>

$ git add .
$ git commit -m "<msg>"
$ git push origin <branch>

After pushing the changes, go to the repository <git-repos> on GitHub and click on the pull request button.

Remove files from Git repository only

To remove files from a Git repository only, use the following commands:

1
2
$ git rm --cached <file>
$ git commit -m "remove file"

View git commit logs

I prefer to use Git Graph from VS Code to see all commit logs. Alternatively, you can use the following commands::

1
2
3
4
$ git log
$ git log --stat
$ git diff <commit-adr>
$ gitk # UI

Pull vs fetch

Pull is a combination of fetch and merge, where fetch crawls codes and pull crawls codes and commits.

Update fork repositories

Here are the steps to update a fork repository:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Add the remote, call it "upstream":
$ git remote add upstream https://github.com/whoever/whatever.git

# Check
$ git remote -vv
# this show:
# origin	https://github.com/maiminh1996/whatever.git (fetch)
# origin	https://github.com/maiminh1996/whatever.git (push)
# upstream	https://github.com/whoever/whatever.git (fetch)
# upstream	https://github.com/whoever/whatever.git (push)

# Fetch all the branches of that remote into remote-tracking branches
$ git fetch upstream

# Make sure that you're on your master branch:
$ git checkout master

# Rewrite your master branch so that any commits of yours that
# aren't already in upstream/master are replayed on top of that
# other branch:
$ git rebase upstream/master

# push 
$ git push origin master --force

Branch

Working with branch

Here are some commands for working with Git branches:

1
2
3
4
5
6
7
8
9
10
11
$ git branch --list # show all branches

$ git branch <branch> # create new branch
$ git branch -d <branch> # delete a branch

$ git checkout <branch> # switch to <branch>

# make change in branch
$ touch test_branch.py # this will create file in all branch
$ git add test_branch.py
$ git commit -m '1st commit' # make file exit only in this branch

Stash changes

You can use Git stash to save locally tracked changes in a stack form. Here’s how:

  • on a branch, all uncommited actions (git rm, touch, etc) will apply to all branches even master. After commit, these changes remain on the branch. So without risk, we do:
1
2
3
4
5
6
7
8
9
10
11
# 0. check branch
$ git branch # check the current branch
$ git stash # stash state
# 1. go to the working branch
$ git checkout <dev-branch>
# 2. check stash work
$ git stash list # list all stash from all branches 
# 3. do some changes
# 4. go to master
$ git stash # this avoids risks
$ git checkout master

when we’re working on a branch and want to switch to another branch, we need to checkout and commit the changement.

However, we want to save it and not commit it, what we need to do: git stash

1
2
3
$ git stash list
$ git diff stash@{<number>} # show changes in stash, e.g. git diff stash@{1}
$ git stash pop stash@{<number>} # reconstruct a specific stash

List all conflict files

You can use the following command to list all conflict files:

1
$ git diff --name-only --diff-filter=U --relative

Merge vs rebase

When integrating changes from one branch into another, Git provides two methods - merge and rebase. The key difference between the two methods is the way Git incorporates changes into the target branch.

  • Merge (recommend) is a process of creating a new commit that combines changes from multiple branches. When you merge a branch into another, Git will create a new commit that has two parent commits, one from the branch being merged, and the other from the target branch. This creates a branch-like structure in the Git history. Let’s say you have created a branch for the purpose of developing a single feature. When you want to bring those changes back to master, you probably want merge (commit).
  • Rebase, on the other hand, is a process of moving changes from one branch to another by reapplying commits on top of another branch. When you rebase a branch onto another, Git will reapply each commit in the rebased branch on top of the target branch, resulting in a linear history. This means that the rebased branch’s commits appear as if they were made directly on top of the target branch’s commits. A second scenario would be if you started doing some development and then another developer made an unrelated change. You probably want to pull and then rebase to base your changes from the current version from the repository.

Merge B to A then solve conficts

1
$ git merge <branch_A> <branch_A> # Merge B to A then solve conficts

Update changes from other branch:

$ git checkout <branch>
$ git rebase origin/master # rebase changes from master to <branch>

Remote

Git allows you to work with remote repositories, which are copies of your repository hosted on a server. You can push changes from your local repository to a remote repository and pull changes from the remote repository to your local repository. Here are some commands for working with remote repositories:

1
2
3
4
$ git remote add <name> <url> # add a repository
$ git remote -v # show all remotes 
$ git remote remove <name> # remote a respo
$ git remote rename <new-name> <current-name> # rename

Others

Some other useful Git tools include:

  • hooks: pre-commit (format code, static analysis)
  • annotate/blame: to see who write each line of code
  • cherry pick: merge with fewer commits

Conclusion

Git is a powerful tool for managing software development projects. Understanding the basic Git commands and best practices can help developers work more efficiently and collaboratively. By using Git effectively, teams can improve code quality, reduce errors, and streamline the development process.

References

  1. Merge vs rebase