原文地址 三年 Git 使用心得 & 常见问题整理
Git 流程图
Workspace
: 工作区
Index/Stage
: 暂存区
Repository
: 仓库区(或本地仓库)
Remote
: 远程仓库
配置 Git
1 2 3 4 5 6 7 8 9 10
| # 配置全局用户 git config --global user.name "用户名" git config --global user.email "git账号"
# 美化log的输出, 并配置别名 alias gll="git log --graph --abbrev-commit --decorate --all --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(dim white) - %an%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n %C(white)%s%C(reset)'";
# 删除全局配置 git config --global --unset alias.xxx git config --global --unset user.xxx
|
查看 Git 信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| git config --list
cat ~/.gitconfig
cat .git/config
git ls-files
git reflog
git --help -a
cat .git/HEAD
git log --online --grep="关键字" --author "username" --before 1 day/1 week/1 "2020-06-15"
|
git reflog
1 2 3 4 5
| $ git reflog cbff89f (HEAD -> master, origin/master) HEAD@{0}: commit: Laravel7 初始化 8b1a09f HEAD@{1}: commit: Laravel7 初始化 c6dcc6b HEAD@{2}: commit: test jenkins f76c78d HEAD@{3}: commit (initial): Laravel7 初始化
|
- 显示的是一个
HEAD
指向发生改变的时间列表。在你切换分支、用 git commit
进行提交、以及用 git reset
撤销 commit
时,HEAD
指向会改变,但当你进行 git checkout -- <filename>
撤销或者 git stash
存储文件等操作时,HEAD
并不会改变,这些修改从来没有被提交过,因此 reflog
也无法帮助我们恢复它们。
git reflog
不会永远保持,Git 会定期清理那些 “用不到的” 对象,不要指望几个月前的提交还一直在那里。
git log 点线图
git 中一条分支就是一个指针,新建一条分支就是基于当前指针新建一个指针
切换至某个分支 ,就是将 HEAD 指向某条分支(指针)
切换至某个 commit ,就是将 HEAD 指向某个 commit
符号解释:
1 2 3 4 5
| * 表示一个 commit | 表示分支前进 / 表示分叉 \ 表示合入 |/ 表示新分支
|
Git 常用命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| git status
git add .
git commit -m "本次提交说明"
git commit -am "本次提交说明"
git push -u origin branch_name
git push
git pull origin branch_name
git merge branch_name
git branch
git branch -a
git checkout branch_name
git stash
git stash pop
|
Git 常用命令详解
add
将工作区的文件添加到暂存区
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| git add [file1] [file2] ...
git add [dir]
git add .
git rm [file1] [file2] ...
git mv [file-origine] [file-renamed]
git add .
git add -u
git add -A
git add .
|
git add .
:操作的对象是“当前目录”所有文件变更,”.” 表示当前目录。会监控工作区的状态树,使用它会把工作区的所有变化提交到暂存区,包括文件内容修改(modified
)以及新文件(new
),但不包括被删除的文件。
git add -u
:操作的对象是整个工作区已经跟踪的文件变更,无论当前位于哪个目录下。仅监控已经被 add 的文件(即 tracked file
),它会将被修改的文件(包括文件删除)提交到暂存区。git add -u
不会提交新文件(untracked file
)。(git add --update
的缩写)
git add -A
:操作的对象是“整个工作区”所有文件的变更,无论当前位于哪个目录下。是上面两个功能的合集(git add --all
的缩写)。
status
1 2
| # 查看工作区和暂存区的状态 git status
|
commit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| # 将暂存区的文件提交到本地仓库并添加提交说明 git commit -m "本次提交的说明"
# add 和 commit 的合并,便捷写法 git commit -am "本次提交的说明"
# 跳过验证继续提交 git commit git commit -n
# 编辑器会弹出上一次提交的信息,可以在这里修改提交信息 git commit
# 修复提交, 同时修改提交信息 git commit
# 加入 git commit
|
push & pull
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
git push <远程主机名> <本地分支名>:<远程分支名> git push origin branch_name
git push origin :branch_name
git push origin --delete branch_name
git push -u origin master
git push
git push --all origin
git pull
git pull origin branch_name
git fetch origin branch_name git merge origin/branch_name
git push --force origin
git push -f orign
|
branch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| # 查看本地分支 git branch | git branch -l
# 查看远程分支 git branch -r
# 查看所有分支(本地分支+远程分支) git branch -a
# 查看所有分支并带上最新的提交信息 git branch -av
# 查看本地分支对应的远程分支 git branch -vv
# 新建分支 # 在别的分支下新建一个分支,新分支会复制当前分支的内容 # 注意:如果当前分支有修改,但是没有提交到仓库,此时修改的内容是不会被复制到新分支的 git branch branch_name
# 切换分支(切换分支时,本地工作区,仓库都会相应切换到对应分支的内容) git checkout branch_name
# 创建一个 caoxl 分支,并切换到该分支 (新建分支和切换分支的简写) git checkout -b caoxl
# 可以看做是基于 master 分支创建一个 caoxl 分支,并切换到该分支 git checkout -b caoxl master
# 新建一条空分支(详情请看问题列表) git checkout --orphan empty_branch_name git rm -rf .
# 删除本地分支, 会阻止删除保护未合并更改的分支 git branch -D branch_name
# 删除远程分支 # 推送一个空分支到远程分支,其实就相当于删除远程分支 git push orign :远程分支名 # 或者 git push origin --delete 远程分支名
# 修改当前分支名 git branch -m branch_name
|
merge 三种常用合并方法
1 2 3 4 5 6 7
| # 默认 fast-forward ,HEAD 指针直接指向被合并的分支 git merge
# 禁止快进式合并 git merge --no-ff git merge --squash
|
fast-forward
:会在当前分支的提交历史中添加进被合并分支的提交历史(得先理解什么时候会发生快速合并,并不是每次 merge 都会发生快速合并);
--no-ff
:会生成一个新的提交,让当前分支的提交历史不会那么乱;
--squash
:不会生成新的提交,会将被合并分支多次提交的内容直接存到工作区和暂存区,由开发者手动去提交,这样当前分支最终只会多出一条提交记录,不会掺杂被合并分支的提交历史
stash
- 能够将所有未提交的修改保存至堆栈中,用于后续恢复当前工作区内容
- 如果文件没有提交到暂存区(使用 git add . 追踪新的文件),使用该命令会提示
No local changes to save
,无法将修改保存到堆栈中
使用场景: 当你接到一个修复紧急 bug 的任务时候,一般都是先创建一个新的 bug 分支来修复它,然后合并,最后删除。但是,如果当前你正在开发功能中,短时间还无法完成,无法直接提交到仓库,这时候可以先把当前工作区的内容 git stash
一下,然后去修复 bug,修复后,再 git stash pop
,恢复之前的工作内容。
1 2 3 4 5 6 7 8 9
| git stash
git stash save "存储"
git stash -u
git stash list
|
diff
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| git diff filename
git diff
git diff --stat
git diff --cached/--staged
git diff branch_name
git diff HEAD
git diff commit1..commit2
|
remote
1 2 3 4 5 6 7 8
| git remote
git remote -v
git remote rm projectname
git remote set-url origin <newurl>
|
tag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| # 默认在 HEAD 上创建一个标签 git tag v1.0
# 指定一个 commit id 创建一个标签 git tag v0.9 f52c633
# 创建带有说明的标签,用 -a 指定标签名,-m 指定说明文字 git tag -a v0.1 -m "version 0.1 released"
# 查看所有标签 git tag
# 查看单个标签具体信息 git show <tagname> # 推送一个本地标签 git push origin <tagname> # 推送全部未推送的本地标签 git push origin --tags
# 删除本地标签 git tag -d v0.1 # 因为创建的标签都只存储在本地,不会自动推送到远程。 # 所以,打错的标签可以在本地安全删除。 git tag -d v0.1 # 删除一个远程标签(先删除本地 tag ,然后再删除远程 tag) git push origin :refs/tags/<tagname>
|
revert
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| # 生成一个撤销最近的一次提交的新提交 git revert HEAD # 生成一个撤销最近一次提交的上一次提交的新提交 git revert HEAD^ # 生成一个撤销最近一次提交的上两次提交的新提交 git revert HEAD^^ # 生成一个撤销最近一次提交的上n次提交的新提交 git revert HEAD~num
# 生成一个撤销指定提交版本的新提交 git revert <commit_id>
# 生成一个撤销指定提交版本的新提交,执行时不打开默认编辑器,直接使用 Git 自动生成的提交信息 git revert <commit_id> --no-edit
|
新建一个 Git 项目的两种方式
本地新建好 Git 项目,然后关联远程仓库
1 2 3 4 5 6 7 8
| # 初始化一个Git仓库 git init
# 关联远程仓库 git remote add <name> <git-repo-url>
# 例如 git remote add origin https:
|
clone 远程仓库
1 2 3 4 5
| # 新建好远程仓库,然后 clone 到本地 git clone <git-repo-url>
# 将远程仓库下载到(当前 git bash 启动位置下面的)指定文件中,如果没有会自动生成 git clone <git-repo-url> <project-name>
|
Git 钩子
pre-commit
pre-commit
就是在代码提交之前做些东西,比如代码打包,代码检测,称之为钩子(hook
)
- 在
commit
之前执行一个函数(callback
)。这个函数成功执行完之后,再继续 commit
,但是失败之后就阻止 commit
- 在
.git/hooks/
下面有个 pre-commit.sample*
,这个里面就是默认的函数(脚本)样本
安装 pre-commit
1
| npm install pre-commit --save-dev
|
配置脚本
如果没有在 .git/hooks
目录下生成 pre-commit
文件的话,则要手工创建 node ./node_modules/pre-commit/install.js
1 2 3 4 5 6 7 8 9
| "scripts": { "build": "tsc", "eslint": "eslint src --ext .ts", "eslint:fix": "eslint src --ext .ts --fix" }, //在提交代码之前,先执行 scripts 中的 eslint 命令 "pre-commit": [ "eslint" ]
|
跳过 pre-commit 继续提交代码
1 2 3
| # 跳过验证 git commit --no-verify git commit -n
|
常见问题
将本地新建的项目上传到新建的远程仓库上
之前没有进行过关联,即没有通过 clone 远程项目到本地再开始做项目,而是先本地新建了一个项目,然后想传到远程仓库上。
1 2 3 4 5 6 7 8
| # 将本地仓库和远程仓库关联起来 git remote add origin 远程仓库地址
# 将本地的 master 分支推送到 origin 主机,同时指定 origin 为默认主机 git push -u origin master
# 上面的命名执行后,下次再从本地库上传内容的时候只需下面这样就可以了 git push
|
不小心把某些文件上传到远程 git 仓库/想要删除远程仓库中的文件
1 2 3 4 5
| # 删除暂存区和工作区的文件 git rm filename
# 只删除暂存区的文件, 不会删除工作区的文件 git rm --cached filename
|
每次 git push 都要输入用户名、密码
1 2 3 4 5 6 7 8 9 10 11 12 13
| # 生成公钥 ssh-keygen -t rsa -C "xxxxx@xxxxx.com"
# 查看已生成的公钥 cat ~/.ssh/id_rsa.pub
# 复制已生成的公钥添加到 git 服务器
# 测试ssh是否能够连接成功 ssh -T git@github.com
# 设置远程仓库 git remote set-url origin git@xxx.com/xxx.git
|