Git is a distributed version control system for managing code history, branches, merges, and team collaboration.
1. Core model
Working Tree(workspace)
↓ git add
Index / Staging Area(Staging area)
↓ git commit
Local Repository(local repository)
↓ git push
Remote Repository(Remote repository)
Three key areas:
| area | function |
|---|---|
| Working Tree | File currently being edited |
| Staging Area | Contents of documents to be submitted |
| Local Repository | Saved Commit History |
Note: git add not only starts tracking the file, but more importantly, puts the snapshot of the current file content of into the staging area.
Therefore, the same file can have both staged and unstaged modifications.
2. Core concepts
Repository
The Git repository contains information such as submission objects, branch references, and historical records.
git init
git clone <url>
The repository usually contains the .git/ directory.
Tracked / Untracked
- Tracked: Files already tracked by Git.
- Untracked: Git Files not yet tracked.
- Modified: The file content has changed.
- Staged: The modification has entered the staging area.
git status
.gitignore
Used to ignore files that are not yet tracked.
node_modules/
.env
dist/
__pycache__/
Files that have been tracked will continue to be tracked even if .gitignore is added.
Stop tracing but keep local files:
git rm --cached .env
If sensitive information has been submitted to the Git history, stopping the tracking will not clear the leaked content in the existing history. You will also need to revoke the corresponding key and consider cleaning the history.
Commit
Commit can be understood as a complete snapshot of the project at a certain moment, and saves metadata such as parent Commit, author, time and submission information.
A ── B ── C ── D
↑
main
Each Commit has a unique object ID.
HEAD
HEAD is usually a symbolic reference to the current branch.
HEAD → main → D
Common expressions:
| expression | meaning |
|---|---|
HEAD | current commit |
HEAD^ | first parent commit |
HEAD~2 | Go forward two times along the first parent commit |
HEAD~3 | Go forward three times along the first parent commit |
HEAD^2 | Second parent commit, common in Merge Commit |
HEAD^3 is not the first three commits, but the third parent commit.
Detached HEAD
Switch directly to a Commit:
git switch --detach abc123
At this time, HEAD points directly to Commit, not a branch.
Good for checking historical code. If you are ready to continue development here, you should create a new branch:
git switch -c fix/old-version
3. Local branches and remote tracking branches
Git is a distributed version control system.
GitHub:
main → C
Local:
main → B
origin/main → C
main: local branch.origin/main: Locally saved remote tracking branch status.origin: The name of the remote repository, usually automatically created by clone.
If a new commit is generated remotely:
GitHub:
A ── B ── C ── D
Local:
main → B
origin/main → C
Run:
git fetch origin
Updated to:
main → B
origin/main → D
But local main will not be modified directly.
fetch and pull
git fetch origin
Get remote updates without merging the current working branch directly.
git pull
Fetch first, then Merge, Rebase or only Fast-forward depending on the configuration.
Explicitly specify:
git pull --no-rebase
git pull --rebase
git pull --ff-only
For scenarios where you want to avoid accidental merge commits, use --ff-only.
4. Basic commands
Initialization and configuration
git init
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git clone <url>
View status
git status
git branch
git branch -a
git remote -v
Staging and submitting
git add src/foo.ts
git add .
git commit -m "feat: add user profile"
git add . Add qualified additions, modifications and deletions in the current directory and subdirectories to the staging area.
It is recommended to check before submitting:
git diff --staged
View differences
# Workspace and staging area
git diff
# staging area and HEAD
git diff --staged
# two Commit
git diff A B
# View a single commit
git show <commit>
View history
git log
git log --oneline
git log --oneline --graph --decorate --all
git log -n 5
git log --author="Author Name"
Among them:
git log --oneline --graph --decorate --all
Suitable for viewing branch and merge relationships.
5. Branch management
Create and switch
git branch feature/login
git switch feature/login
# Create and switch
git switch -c feature/login
Delete
# safe delete
git branch -d feature/login
# force delete
git branch -D feature/login
# Delete remote branch
git push origin --delete feature/login
-d checks that the branch has been merged appropriately; -D skips this safety check.
Rename
git branch -m new-name
Push with Upstream
git push -u origin feature/login
-u establishes the tracking relationship between the local branch and the upstream branch.
After that you can usually:
git push
git pull
But the actual Push target is also affected by the Git configuration.
6. Merge: merge branches
Assumptions:
C ── D feature
/
A ── B ── E main
On main:
git switch main
git merge feature
Result:
C ── D ──┐
/ │
A ── B ── E ───── M
↑
main
Merge Commit M has two parent commits.
Git performs a three-way merger based on common ancestors and changes on both sides.
Fast-forward Merge
If main produces no new commits:
A ── B main
\
C ── D feature
Execution:
git switch main
git merge feature
Result:
A ── B ── C ── D
↑
main, feature
At this time, Git only needs to move the branch pointer forward, and does not necessarily create a new Merge Commit.
7. Rebase: Rebase
Assumptions:
A ── B ── C main
\
D ── E feature
Execute on the feature branch:
git switch feature
git rebase main
Result:
A ── B ── C main
\
D' ── E' feature
Rebase After reapplying the commits in the branch to the new base commit.
A new Commit ID is usually generated due to changes in information such as the parent commit.
Merge and Rebase
| Contrast | Merge | Rebase |
|---|---|---|
| original history | Reserve | Rewrite a replayed commit |
| Submit diagram | May produce forks and Merge Commit | usually more linear |
| shared branch | relatively safe | should not be rewritten arbitrarily |
| Common uses | Merge feature branches | Update personal development branch |
Common principles:
- History that has been shared by the team should be given priority to avoid Rebase rewriting.
- For function branches that are maintained independently, you can use Rebase to organize the history.
- The details are subject to the team’s Git workflow specification.
8. Merge / Rebase conflict
Conflict example:
<<<<<<< HEAD
const timeout = 30;
=======
const timeout = 60;
>>>>>>> feature
The final content needs to be manually determined and conflict markers removed.
Merge conflict
git status
# Modify conflict files
git add config.ts
git merge --continue
You can also execute git commit to complete the merge under appropriate circumstances.
Give up Merge:
git merge --abort
Rebase conflict
git status
# Modify conflict files
git add config.ts
git rebase --continue
Give up Rebase:
git rebase --abort
Note: When Rebase, the meanings of ours and theirs are easily confused with ordinary Merge, and cannot be mechanically understood as "my code" and "other people's code".
9. Restore、Reset、Revert
All three orders relate to revocation but have different responsibilities.
git restore
Mainly restore the file contents in the work area or staging area.
# Discard unstaged modifications to the file and revert to Index
git restore src/foo.ts
# Cancel the temporary save and keep the workspace modifications
git restore --staged src/foo.ts
# Both the staging area and the workspace are restored to HEAD
git restore --source=HEAD --staged --worktree src/foo.ts
Note: By default git restore file uses Index as the source, which is not necessarily equal to HEAD.
git reset
You can move the Commit pointer of the current branch and decide whether to modify the staging area and work area according to the mode.
| mode | Move HEAD | Reset Index | Reset Working Tree |
|---|---|---|---|
--soft | Yes | No | No |
--mixed (default) | Yes | Yes | No |
--hard | Yes | Yes | Yes |
For example:
# Undo the last Commit,keep staging
git reset --soft HEAD~1
# Undo the last Commit,Keep workspace modifications but unstage them
git reset HEAD~1
# Return to the specified commit and reset the workspace and staging area
git reset --hard abc123
--hard is destructive and may cause uncommitted work to be lost. For commits that have been pulled by others, you generally should not force push them after Reset.
When specifying a file:
git reset HEAD -- src/foo.ts
Just restore the temporary contents of the file to HEAD without moving the current branch.
git revert
Create a new reverse commit without deleting the original history.
A ── B ── C ── D
↓ revert C
A ── B ── C ── D ── E
git revert <commit>
Suitable for commits that have been Push to the team's shared branch.
How to choose?
| demand | Recommended |
|---|---|
| Discard unstaged modifications | git restore |
| Unstage | git restore --staged |
| Undo the unpushed Commit and retain the modifications | git reset --soft |
| Undo Commit on shared branch | git revert |
| Completely discard local modifications and roll back | git reset --hard, cautious |
10. Last modification Commit
Modify submission information:
git commit --amend
Forgot to add file:
git add forgotten.py
git commit --amend --no-edit
--amend actually creates a new Commit replacing the old Commit at the end of the current branch.
Use caution if old commits have been Push into the shared branch.
11. Stash: Temporarily save changes
git stash is used to temporarily save uncommitted work.
git stash
The default is to save staged and unstaged modifications of tracked files, but not ordinary Untracked files.
New files need to be included:
git stash push -u -m "WIP: profile form"
Commonly used commands:
git stash list
# Restore the latest Stash,and remove from the list
git stash pop
# restore but retain Stash
git stash apply
# delete specified Stash
git stash drop stash@{0}
Suitable for temporary switching tasks during development.
Note: stash pop may conflict and the recovery process may not be successful.
12. Cherry-pick: Select the specified submission
Assumptions:
main: A ── B ── C
feature: A ── B ── D ── E
Just want to apply the modifications of D to main:
git switch main
git cherry-pick <D>
Result:
main: A ── B ── C ── D'
Applicable scenarios:
- Pick Bug Fix from other branches.
- Backport specific fixes to release branches.
- Don't want to merge the entire feature branch.
Cherry-pick usually creates a new Commit.
13. Reflog: Retrieve lost commits
git reflog records some historical changes of local HEAD and references.
git reflog
For example, executed:
git reset --hard HEAD~2
If you find that the rollback is wrong, you can first pass:
git reflog
Find the original Commit ID.
Then create the recovery branch:
git branch recovery <commit-id>
Or try Reset again after confirming safety.
Need to pay attention to:
- Reflog is mainly a local record.
- Reflog entries will expire.
- There is no guarantee that all uncommitted changes can be retrieved.
It is especially suitable for recovering Reset, Rebase not found after accidental Commit.
14. Tag: version label
Tag is typically used to mark release versions.
Lightweight tags:
git tag v1.0.0
Note tags:
git tag -a v1.0.0 -m "Release v1.0.0"
Push:
git push origin v1.0.0
Check out:
git tag
git show v1.0.0
Tag is different from Branch:
- Branch usually moves with the new Commit.
- Tag usually points to a specific object.
15. Force push
git push --force
Remote branch history can be forcibly overwritten, which carries a higher risk.
It is more recommended to use when you really need to rewrite your own branch history:
git push --force-with-lease
It checks that remote references still match local expectations, reducing the risk of overwriting someone else's new commit.
But it does not mean absolute safety, especially in background Fetch or complex team collaboration scenarios, you still need to be cautious.
Do not force push the shared main branch at will.
16. Daily development workflow
Step 1: Create a feature branch
git switch main
git pull --ff-only
git switch -c feature/avatar-upload
Step Two: Develop and Submit
git status
git diff
git add .
git diff --staged
git commit -m "feat: add avatar upload"
Step 3: Push
git push -u origin feature/avatar-upload
Create Pull Request at GitHub, waiting for Review.
Step 4: Modify according to Review
git add .
git commit -m "fix: validate avatar file type"
git push
Step 5: Clean up after PR merge
git switch main
git pull --ff-only
git branch -d feature/avatar-upload
If the remote function branch is not automatically deleted by the platform, it can be deleted on demand:
git push origin --delete feature/avatar-upload