Git Guide

Posted by Daksh on Wednesday, May 11, 2022

Git

Staging and Committing

git init
git status
# untracked files -> test.txt 
git add test.txt
git status
# staged files -> test.txt
git restore --stage test.txt
git status
# untracked files -> test.txt
git add test.txt
git commit -m "Initial commit"

Git Branches

Branches are used to develop features isolated from each other. The master branch is the default branch when you create a repository. Use other branches for development and merge them back to the master branch upon completion.

Creating a branch

To create a new branch and switch to it, use the git checkout command with the -B flag.

# method 1
git checkout -B <branch_name>
# e.g. git checkout -B feature_x

# method 2
git branch <branch_name>
# e.g. git branch feature_x

Git branch command only creates a new branch, it doesn’t switch to it. To switch to the new branch, use the git checkout command with the -B flag.

Run git branch to list all the branches in the repository, with the current branch indicated by a * symbol.

The main branch has no knowledge of the new branch even if the code is pushed to the remote repository. Git branches exist in isolation. And therefore, changes need to be merged back to the main branch. This is done by creating a pull request.

To have multiple feature branches, you can name them as feature/<feature_name>. This is a convention used by many teams.

Pull Requests

The purpose of a pull request is to obtain a peer review of changes made to the branch and to validate that the changes are correct.

# continuing from the previous example
git checkout -B feature_x
touch test2.txt
git add test2.txt
git commit -m "Add test2.txt"
# -u flag sets the upstream branch
# this means that the origin will not be the main branch anymore
git push -u origin feature_x
# go to github (warlock-spell) and create a pull request
# the pull request will then be merged by the owner of the repository
# once the pull request is merged, the branch can be deleted or kept
# to receive the latest changes from the remote repo, use the following command
git checkout main
git pull

Working with Remotes

If it is the first time you need to clone a repository, else use git pull to get the latest changes.

Use git remote -v to list all the remote repositories.

To add a remote repository, use the git remote add command.

git init
git remote add origin <git_url>
git pull
ls
# no files, because there is no main branch
git checkout main
ls
# test.txt

Push and Pull

Git distributed workflow is synchronized by using the git push and git pull commands. Push is used to send changes to the remote repository. Pull is used to receive changes from the remote repository.

Before pushing, you need to pull the latest changes from the remote repository. This is to ensure that you are not overwriting any changes made by other people and to avoid merge conflicts.

If there are no merge conflicts, auto-merge will be performed. If there are merge conflicts, you will need to resolve them manually.

Resolving conflicts

Conflicts will normally occur when you try to merge a branch that may have competing changes. Git will normally try to automatically merge (auto-merge), but in the case of a conflict it will need some confirmation, the competing changes need to be resolved by the end user. This process is called merging or rebasing.

Tracking HEAD

HEAD is a pointer to the current branch. It is used to track the current branch. It is also used to track the current commit.

git init
cd .git
cat HEAD
# ref: refs/heads/main
cat refs/heads/main
# 6d4b8c9e8b1b4b9c9e8b1b4b9c9e8b1b4b9c9e8b -> reference to the current commit
cd ..
git checkout testing
git branch 
# * testing, main

cat .git/HEAD
# ref: refs/heads/testing

Tracking changes in files

git status is used to check which files have been modified and git diff is used to check what changes have been made to the files. When used together, they can act like a file system.

To track changes in a file with the current commit, use git diff HEAD <file_name>. This will show the changes made to the file since the last commit. Individual files, branches, and commits can all be compared with Git diff. To compare the current branch with another branch, use git diff main <branch_name>.

Logging commits

git log is used to view the commit history. It shows the commit hash, author, date and commit message. Use git log -3 to view the last 3 commits. Use git log --pretty=oneline to view the commit history in a single line. To view the commit history spread across multiple pages, use arrow keys to navigate and q to quit.

Blame

git blame is used to view the commit history of a file. It shows the commit hash, author, date and commit message. It also shows the line number and the content of the line. Use git blame <date> <file_name> to view the date, time and author of the commit. Git blame lists the entire file, with commit information for each line. It is useful for finding out who made a change to a particular line of code. To view specific lines, use git blame -L <start_line>,<end_line> <file_name>. To see commit id in full length, use git blame -l <file_name>. Git blame will display to you the point where it was changed, git log will give you the detail of the change. Always use the two in conjunction to get more details about what changes occurred.

Commit message format in Blame

The commit message should be in the following format:

93598933 # id of the commit
( Author: <author> 
Date:   <date> 
Time:   <time> 
Line number: <line_number> # where the change was made
<content> # the content of the line
)

Forking

Forking is a way to create a copy of a repository. Forking is used to contribute to a project without having to have write access to the repository. Forking is also used to create a copy of a repository to use as a template for a new project. Forking is another type of workflow. The key difference between branching and forking is that the workflow for forking creates a new repository entirely. Branching cuts a new branch from the same repository each time and each member of the team works on the single repository.

The Pull Request compares the two repositories and the changes made to the forked repository. The Pull Request is then merged into the original repository. Use Fetch upstream drop-down to allow you to pull and merge the latest changes from the original repository.

References