Git
配置
git config --global user.name "your_username"
git config --global user.email "your_email"
# 查看所有配置
git config -l
初始化
# 初始化指定目录
git init git-demo
# 初始化当前目录
git init
查看状态
git status
git status -s # 简化版
# short format
# ?? file # 文件未追踪
# A file # 文件已添加
# M file # 文件被修改
# M file # 文件被修改且已加入暂存区
标识
- SHA1标识:f1dfde5930bb26b7e94738481aca2bad6fc74b39
- 可以使用缩写,只写前4+位
- HEAD引用:指向当前分支的最新修订
- HEAD^n:当HEAD或标识存在分支合并时,指向第n个父修订
- HEAD~m:指向第m个祖先修订
- HEAD^n~m:指向第n个父修订的第m个祖先修订
- HEAD@{k}:指向倒数第k个历史操作指向的修订
- 分支引用:指向所指分支的最后一个修订
查看历史记录
查看提交记录
git log
git log --graph
git --no-pager log # 输出到stdout
git log --oneline # 一行展示
# 查看最近3条记录,-3表示输出不查过3行
git log HEAD -3
# 查看离 e85fe7 最近3条记录
git log e85fe7 -3
# 单行显示
git log --abbrev-commit --pretty=oneline
# 只显示提交备注
git log --pretty=format:'%s'
# 配置alias
git config --global alias.hist 'log --pretty=format:"%h %ad | %s%d [%an]" --date=short'
git hist
git config --global alias.graph 'log --graph'
git graph
git config --global alias.mist 'log --pretty=format:"%s"'
git mist
查看提交
# 查看 e85fe7 的修订记录
git show e85fe7
# 查看倒数第2次记录
# HEAD: 当前修订,等于HEAD~0
# HEAD~1: 前一个修订
# HEAD~2: 前两个修订
git show HEAD~2
查看文件差异
# ckeck difference
git diff
git diff --name-only # 只显示文件名
git diff --stat # 显示统计信息
# 查看倒数第二次修订和当前修订中,file1文件的差异
git diff HEAD~1 HEAD file1
difftool
在 ~/.gitconfig
中写入一下配置
[diff]
tool = vscode
[difftool "vscode"]
cmd = code --wait --diff $LOCAL $REMOTE
然后可以在 vscode 中查看 diff 内容
git difftool {{branch you want to check with}}
查看操作记录
git reflog
工作区(working directory)
修改/撤销修改
# 修改文件
echo hello > file1
# 撤销修改
git reset HEAD --hard
git stash # 实际上是将更改存入栈中,需要时可以git stash pop取出来
git clean -fd # 清除所有未提交的修改
# 将未暂存的文件修改丢弃,退回到暂存区/版本库
git checkout -- file1
# or
git restore file1
# 撤销所有修改
git checkout -- .
# or
git restore .
# 修改提交信息
git commit --amend
暂存区(staging area)
加入/撤销暂存区(staging area)
git add
加入暂存区的是对文件的修改而不是文件,因此文件每次修改都要add
# 加入暂存区
git add bugfile
git add featurefile
# 如果只想加入一个文件内的一部分修改,则需要创建hunk
git add -p
# 移出暂存区
git reset featurefile
# 将所有修改移出暂存区
git reset .
提交
git commit -m "update"
# 将所有未暂存的修改暂存然后提交,但是不会暂存未追踪的文件
git commit -m "update" -a
# 撤销提交
git reset HEAD # HEAD 表示当前commit,将未commit的修改放回工作区,但是不会修改文件内容
git reset HEAD --hard # HEAD 表示当前commit,丢掉所有未commit的修改,包括工作区和暂存区
git reset HEAD~1 # HEAD~1 表示前一个commit,与当前文件不一致的会放回工作区
git reset HEAD~1 --hard # HEAD~1 表示前一个commit,立刻让所有文件变为前一个commit的样子
# 恢复撤销
# 列出所有操作
git reflog
# 恢复到reflog中的第1个操作时
git reset HEAD@{1}
# --hard表示同时覆盖工作区和暂存区的文件
git reset --hard HEAD@{1}
Tag
# 查看 tag
git tag
# 添加 tag
git tag -a v1.4 -m "my version 1.4"
# 删除 tag
git tag -d v1.4
# checkout tag
git checkout v2.0.0
git checkout tags/v2.0.0
# push tag
git push origin v2.0.0
分支
# 查看分支
git branch
git branch -a # 查看所有分支
# 创建分支
git branch dev
# 切换分支
git checkout dev
git checkout -b dev # 创建并切换分支
# 合并分支
git merge dev # 直接将master的指针指向dev的最后一个commit,同时合并dev之前所有的commit
git merge --no-ff -m "merge with no-ff" dev # 会在dev最后一个commit的基础上,创建一个新的commit
git merge dev --squash # 将分支的所有修改同步到暂存区,但是不commit,需要一次手动commit,好处是dev分支的commit记录并不会同步到master分支
# rebase
git rebase -i HEAD~3 # rebase最近三次commit
# 通过rebase合并分支
git rebase dev
git add --all # 修订完所有conflict后
git rebase --continue
# 删除分支
git branch -d dev
git branch -D dev # 删除还没合并的分支
# 批量删除多个分支
git branch -D $(git --no-pager branch --list 'bugfix*')
# 把当前分支全部修订搬移到指定分支,两个分支的历史合并成一条线
git rebase dev
远程仓库
# 查看远程仓库
git remote
git remote -v
# 给远程仓库取别名,一般是origin
git remote add origin http://git.example.com
# 推送到远程仓库
git push origin master
git push origin dev
# 拉取仓库
git fetch origin
# 在本地创建和远程分支对应的分支
git checkout -b branch-name origin/branch-name
# 建立本地分支和远程分支的关联
git branch --set-upstream branch-name origin/branch-name
# 抓取远程的新提交
git pull
git pull origin dev # 等价于先拉取然后merge => git fetch origin; git merge origin/master dev
git pull -r origin dev # 在pull的时候使用rebase
# 修改远程仓库地址(例如远程仓库换域名了)
git remote set-url origin git@new.host:srv/project
搭建Git服务器
- 创建git用户
sudo adduser git
sudo passwd git
- 把所有公钥导入到
/home/git/.ssh/authorized_keys
- 初始化Git仓库
cd /home/git/srv
mkdir sample.git
sudo git init --bare sample.git
sudo chown -R git:git sample.git
- 禁用shell登录
在/etc/passwd
中加上git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
- 克隆远程仓库
git clone git@server:srv/sample.git
Github
Clone from github
git clone https://github.com/cyzlmh/cyzlmh.github.io
# with token
git clone https://cyzlmh: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@github.com/cyzlmh/cyzlmh.github.io
Submit changes
git add --all
git commit -m "some comments"
git push -u origin master
# make quick push alias
alias quick-push='git add --all && git commit -m "update" && git push -u origin master'
Push local dir
git init
git add --all
git commit -m "init"
git remote add origin 'https://github.com/cyzlmh/cyzlmh.github.io'
Utils
Git Ignore
Pattern | Example matches | Explanation |
---|---|---|
*.log | debug.log | 所有文件夹中满足的 pattern 的 |
logs/ | logs/debug.log | 所有满足的 pattern 的文件夹中的文件 |
/debug.log | /debug.log | 根文件夹中满足的 pattern 的文件 |
示例
# MacOS
.DS_Store
# logs
*.log
logs/
# binary
bin/
汇总:https://github.com/github/gitignore
自动创建.gitignore
:https://www.toptal.com/developers/gitignore
Git-lfs
github - Git Large File Storage
install
# macos
brew install git-lfs
# ubuntu
sudo apt-get install git-lfs
# centos
sudo yum install git-lfs
清除.DS_Store
find . -name .DS_Store -print0 | xargs -0 git rm -f --ignore-unmatch
echo .DS_Store >> .gitignore
git add .gitignore
git commit -m '.DS_Store banished!'