三年 Git 使用心得 & 常见问题整理

原文地址 三年 Git 使用心得 & 常见问题整理

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

# 查看当前项目的git配置
cat .git/config

# 查看暂存区的文件
git ls-files

# 查看本地git命令历史
git reflog

# 查看所有git命令
git --help -a

# 查看当前HEAD指向
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 "本次提交说明"

# add和commit的合并,便捷写法(未追踪的文件无法直接提交到暂存区/本地仓库)
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 2.0 以下版本
# 只作用于文件的新增和修改
git add .
# 只作用于文件的修改和删除
git add -u
# 作用于文件的增删改
git add -A

# Git 2.0版本
git add . // 等价于 git add -A
  • 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 --no-verify
git commit -n

# 编辑器会弹出上一次提交的信息,可以在这里修改提交信息
git commit --amend

# 修复提交, 同时修改提交信息
git commit --amend -m "本次提交的说明"

# 加入 --no-edit 标记会修复提交但不修改提交信息, 编辑器不会弹出上一次提交的信息
git commit --amend --no-edit

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
# 如果当前分支与远程分支存在追踪关系则可以省略分支和 -u
git push

# 不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机
git push --all origin

# 拉取所有远程分支到本地镜像仓库中
git pull

# 拉取并合并项目其他人员的一个分支
git pull origin branch_name
# 等同于 fetch + merge
git fetch origin branch_name
git merge origin/branch_name

# 如果远程主机的版本比本地版本更新,推送时 Git 会报错,要求先在本地做 git pull 合并差异,
# 然后再推送到远程主机。这时,如果你一定要推送,可以使用 –-force 选项
# (尽量避免使用)
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

git merge

  • 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
# 查看工作区与 HEAD 指向(默认当前分支最新的提交)的对比
git diff HEAD

# 查看两个commit的对比
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://github.com/xxxxxx

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

Powered by Hexo and Hexo-theme-hiker

Copyright © 2017 - 2021 Keep It Simple And Stupid All Rights Reserved.

访客数 : | 访问量 :