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
- source code
- automated tests
- server configuration
- a book
- web site content
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 "email@example.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.
git status to view file status tracked by git.
Step 2. Add staged files to local repo using
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
-u is to link the current local repo to the origin remote repo.
master label represents the tip of the local
origin/master label represents the tip of the tracking branch (defined as a local branch that represents the remote branch) of remote repo
master branch. It can become out of sync with local branches, one updates it by using
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.
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).
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
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>
Best practice: create small and frequent merges
- Fast forward (FF) merge (creates a linear git history). This type of merge assumes nothing was done on base branch after the
branch_to_mergewas created. The fast forward merge only updates HEAD reference from old place to the updated place on a feature branch (see below).
- Merge commit (creates a new commit by merging lastest commits of merged branches, it has multiple parents. Use
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.
- checkout master -
git checkout master
- merge featureX: conflict (
git merge featureX) - both modified fileA.txt (
git statuswill show you this)
- fix fileA.txt
- stage fileA.txt -
git add fileA
- commit and merge commit -
git commit -m "message"
- optionally remove
Git rebase rewrites commit history.
Rebasing is a type of merge. Git changes one branch’s parent to a commit of another branch.
becomes A <–B <–C’
git checkout featureX git rebase master # is same to git rebase master featureX
Fixing a merge conflict when rebasing:
git checkout featureX
git rebase master: might have conflict
git status: find conflict, resolve it
git add file_with_conflict
git rebase --continue
Amend a commit
- change commit files but not the message
git commit --amend --no-edit
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 interactive rebase
git rebase -i the_1st_parent_of_commit_to_modify
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.
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.