Git
Source Control
Git is a tool to track changes in a working directory(repository), a perfect tool to control the version of developement in local enviroment. While GitHub is an online repository platform allowing developers to save, share and deploy codes online.
Online Git Platform
| Feature | GitHub | GitLab | Bitbucket |
|---|---|---|---|
| Free Repos | Unlimited | Unlimited | Limited to 5 users |
| CI/CD | GitHub Actions | Built-in | Pipelines |
| Self-Hosting | No | Yes | Yes |
| Integration | Widely supported | GitLab-exclusive | Atlassian tools |
| Best For | Open-source projects, team collaboration | Enterprises and teams focused on DevOps workflows | Teams using Atlassian tools |
Workflow and Concept
Three trees maintained by git
- Working Directory: to be added to Index
- Index(staging area): to be commited to HEAD
- HEAD: a current pointer in branch
origin: default name of remote repository when cloned, main: mainline branch of project, master: legacy name of main. To make different code from main branch, ALWAYS create a new branch and merge after completion. Checkout switches working directory to the target branch.
Getting Started
git init # Create git repository
git add . # Staging
git commit -m "Initial Commit Message"
Branching and Merging
# Create a branch or move to a branch
git branch <branch_name>
# Move to a branch
git checkout <branch_name>
# Create and switch to new branch
git checkout -b <branch_name>
# Delete unused branch
git branch -d <branch_name>
# Merge HEAD to a branch
git merge <branch_name>
Revert
Revert reverse the change, it will add a new commit so that the branch is now the same as its previous parent. This is recommended for collaborative work.
git revert HEAD
Rebase
Rebase moves entire branch in HEAD to begin on the tip of a branch. It is better for a cleaner linear history. But are not suitable for beginer and collaboration.
git rebase <branch_name>
Interactive Rebase
# Interactive rebase: pick the arrangement of a branch into a new branch
git rebase -i HEAD~4
git rebase <destination_branch> <source_branch>
Dealing with Conflict
Modern IDE have built-in tools to deal with conflict. You can compare two files and pick the changes you want to keep. Without it, here is the manual way.
# Show the conflict, edit the files to resolve conflict
git status
# After resolving conflict
git add <filename>
# Preview before merging
git diff <source_branch> <target_branch>
# Cancel merge
git merge --abort
Detach
Detach is a way to move a HEAD to previous commit. It will not destroy anything. Commiting on detached HEAD will not be save. It is purely "watch".
git checkout <commit_id>
# Move to the parent of branch_name
git checkout <branch_name>^
# Move to the second parent of branch_name
git checkout <branch_name>^2
# Move to the n-th parent of branch name
git checkout <branch_name>~n
# Force the first branch to the parent of second branch. Unable to work on current branch. The moved branch will lost it's commit
git branch -f <branch_name> <branch_name>^
Reset
Reset reverse the changes by moving a branch to its parent. But it only works on local.
git reset HEAD~1
# Undo previous commit on branch (Keeps staging and working directory)
git reset --soft HEAD~1
# (Default) Undo previous commit on branch + staging (Clear stage and keep working directory) Suitable for mixing two commits for a cleaner history
git reset --mixed HEAD~1
# Undo previous commit on everything
git reset --hard HEAD~1
Cherry-pick
# Cherry-pick picks the commits to be added into HEAD
git cherry-pick <commit1> <commit2>
Trick to move commits: accidentally committed work to
maininstead offeature. You can checkoutfeature, cherry-pick the commit there, then go back tomainand delete it.
Pushing and Pulling
# Fetch and merge remote changes to stay synced
git pull
# Remove references to branches that no longer exist on the remote
git fetch --prune
git pull --rebase
# Update a remote branch
git push origin <branch_name>
# Update all remote branch
git push --all origin
# Delete a remote branch
git push origin --delete <branch_name>
# Force delete a remove commit after local commit is reseted
git push origin <branch-name> --force
# Inspect remote branches
git remote show origin
# Create a branch from remote
git checkout -b main origin/main
Tagging
Tags for software release. The code is the first 10 characters of commit id. View log for commit id details.
git tag 1.0.0 1b2e1d63ff
Logging
git log
git log --author=bob
git log --pretty=oneline
git log --graph --oneline --decorate --all
git log --name-status
git log --help
Replace local changes
# Replace these files into previos update
git checkout -- <filename>
# Forget local and use newest from server
git fetch origin
git reset --hard origin/master
Hints
# built-in git GUI
gitk
# use colorful git output
git config color.ui true
# show log on just one line per commit
git config format.pretty oneline
# use interactive adding
git add -i
Reference: git-guide Visual Tutorial: Learning Git
GitHub
To use GitHub, create a repository on Github and copy the repository link https://github.com/username/repository.git.
git remote add origin https://github.com/username/repository.git
git push -u origin main
GitHub repository have its own branch based on GitHub users. On each branch of user, the repository have its own branch. After a user fork a GitHub repository, that user can open a Pull Request to merge the fork back to the original branch and is to be reviewed by the original author.
Multiple Remote
Add GitLab as a second remote
git remote add gitlab https://gitlab.com/yourusername/yourrepo.git
# Set origin to push to BOTH GitHub and GitLab
git remote set-url --add --push origin https://github.com/yourusername/yourrepo.git
git remote set-url --add --push origin https://gitlab.com/yourusername/yourrepo.git
# Now a single push goes to both
git push origin main
# Option B
git push origin main # → GitHub
git push gitlab main # → GitLab
Git on VS Code
VS Vode comes with a pre-built git UI system. It will detect a git repository on the opened folder and display on Source Control. Here are some common functions:
- Click
commitand insert the message to update graph tree. Conflict resolver will appear automatically if needed. - Create and checkout branch on
More Action... - Press
Fetch From All Remotesand clickSYNCto update to latest remote repository
Alternately, Git Graph extension is also quite intuitive and easy to manage git visually.