Git essentials

Learning note from “Version Control with Git” by Atlassian offered by Steve Byrnes on Coursera.

Git common usage

Types of content for git

Basically any content you want to manage and continuously improve

Git setup

Configure user name and email address: --global flag to configure every repo on a given computer, --local flag (or no flag) only applies to the current repo.

git config --global user.name "first last"

git config --global user.email "xyz@gmail.com"

From local repo to remote repo

Scenario 1. You have not started working on anything and you plan to build on top of an existing repo. Go to the remote repo site and copy the url that ends with .git (such as https://xyz.git).

git clone https://xyz.git to local dir. Go to step 1 below after that.

Scenario 2. You did a lot of work locally and now you want to add them to a remote git repo.

git init to initialize a .git dir, which contains information about git. Delete .git dir will remove all the git histories. Create (no need to init additional files otherwise there will be conflicts) or identify a remote repo (e.g https://xyz.git, use git pull https://xyz.git if this repo is not empty )

git remote add origin https://xyz.git, origin is a name we call the remote repo by default.

git remote --verbose to see the details of remote repo.

After this point, the remote repo is all setup. Let’s look at how to let git know the changes we made to local repo:

Step 1. Stage files using git add <filename_x>, filename_x will be tracked by git after this step. Before this step, filename_x would be either untracked by git or tracked by git but had not been updated.

Use git status to view file status tracked by git.

Step 2. Add staged files to local repo using git commit.

Use git log to see the history of commit messages, --all tag to show all branches.

git log --oneline --graph --all

Step 3. Push current ‘commits’ to remote repo using git push to a specific branch.

git push --set-upstream origin master means you want to push all commits of the current repo to the master branch of a remote repo called origin. -u is to link the current local repo to the origin remote repo.

Vocabulary:

The master label represents the tip of the local master branch.

The origin/master label represents the tip of the tracking branch (defined as a local branch that represents the remote branch) of remote repo origin‘s master branch. It can become out of sync with local branches, one updates it by using git clone/fetch/pull/push.

git pull combines a fetch and a merge, it is recommended to do git pull before git push, as there might be updates made by other people to the remote repo.

git push adds commits to remote repo.

Advanced usage

Git references

Git has one HEAD per repo. HEAD usually points to the current commit. Use git show HEAD to show the HEAD content. Checking out a past commit will create a “Detached HEAD” state (updated HEAD reference). One can checkout a past commit and make a branch off there (see how in “Git branches” section).

Git tags

Tag is a reference attached to a single commit. One can tag a commit to sign off a release. Annotated tags are more useful because you can associate it with more info.

#tag a commit, -a means annotated, -m is for message
git tag -a -m "message associated with this tag" <tagname> [commit_ID]

#tag current commit
git tag -a -m "message associated with this tag" <tagname>

# show available tags
git tag 

# show specific info (commit info) of a tag
git show <tagname>


Tags need to be independently pushed by git.

#for a single tag
git push <remote> <tagname> 

# for all tags
git push <remote> --tags

Git branches

Allow independent work of many people on a project without conflict.

Make a new branch and update HEAD reference to the new branch. -b only works when the new branches hasn’t been created.

git checkout -b new_branch_name

The above is equalvent to

git branch new_branch_name 
git checkout new_branch_name 

Switch to an existing branch (update HEAD reference)

git checkout exsiting_branch_name

Delete a branch (usually done after merging branch_to_delete content to master branch). If branch_to_delete has commits that haven’t been merged, one can still use -D to delete the branch but this will create “Dangling commits”, eventually these commits will be garbage collected and removed.

git branch -d branch_to_delete

Undo an accidental branch delete

# The accidental deletion of branch
git branch -D branch_to_delete 

# get local recent commits
git reflog

# find dangling commits from local commits and re-create the branch
git checkout -b new_branch_name <commit_ID>


Git merge

Best practice: create small and frequent merges

git checkout common_base

git merge --no-ff new_feature_branch

Solving merge conflicts

Merge conflicts occur when a same file is edited in different ways on two branches, and one wants to merge these two branches.

How to:

Git rebase

Git rebase rewrites commit history.

Rebasing is a type of merge. Git changes one branch’s parent to a commit of another branch.

A <–B
\<—C

becomes A <–B <–C’

git checkout featureX
git rebase master

# is same to 
git rebase master featureX

Fixing a merge conflict when rebasing:

Rewriting history

Amend a commit

git commit --amend --no-edit

Squash merge

git checkout master
git mrege --squash featureX
git commit 

More advanced usage (e.g edit commit message, drop/delete commits, squash, fixup, reorder commits)

 git rebase -i the_1st_parent_of_commit_to_modify

Pull request

The goal of a pull request is to merge a branch by asking specific reviewers to approve the merge before it happens. Pull request can be opened anytime after a branch is made. No need to edit the pull request if one add more commits to the branch.

Contribute others repo using fork

Forking a remote repo creates a different source of truth, one usually forks other people’s repo and works on it so that it can be merged to the the upstream repo (where it was forked from) with a pull request.

Git workflow

Contains long running branches and short-lived branches. The master and develop branches are only the long running branches. Releases only happen on master, and are tagged. Most of the work are done on develop branch, feature branches are add-ons and will be merged to develop branch and deleted afterwards. Bugfix branch (release1) is short-lived and will be merged to both develop and master branches. Hotfix branch for released features is branched off master branch, because there could be more work done on develop branch since the release. See below graph taken from the course.