git常用指令

安装git

1.windows系统

官网下载对应应用程序安装即可

2.linux系统

centos yum -y install git

ubuntu apt-get install git

配置信息

1.配置用户信息

1
2
3
4
5
6
# 设置全局参数
git config --global user.name <用户名>
git config --global user.email <邮箱>
# 设置仓库内参数
git config --global user.name <用户名>
git config --global user.email <邮箱>

仓库创建

1.本地初始化仓库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 把当前目录初始化为仓库
git init
### 路径管理 ###
# 在当前目录下创建 ./仓库名 路径用于存储仓库
git init <仓库名>
### 分支管理 ###
# 设置初始分支名,默认为master
-b <branch-name>
### 权限管理 ###
# 设置仓库的访问权限
--shared[=(false|true|umask|group|all|world|everybody|<perm>)]
# umask false # 默认选项
# 各用户获得其umask对应的权限(存疑?)
# 具体参考https://blog.csdn.net/Doudou_Mylove/article/details/118384471
# 例:root的umask为022,其创建目录时对应权限为777-022=755,创建文件时对应权限为666-022=644
# group true
# 当前用户组拥有读写权限
# all world everybody
# 任意用户拥有读权限,其他权限与group类型相同
# <perm>
# (存疑?)

2.从远程拉取仓库

1
2
3
4
# 拉取仓库
git clone <仓库地址>
# 拉取指定分支
git clone --branch <分支名> --single-branch <仓库地址>

本地仓库管理

1.暂存区管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 将<文件名>文件添加至暂存区(即index文件中)
git add <filename>
# 将匹配.append后缀的所有文件添加至暂存区
git add *.append
# 添加所有文件至暂存区
git add .
# 恢复目标文件至上次 git add 的状态
git restore <file>
# 从暂存区中撤销目标文件,但是不修改其在工作区的状态
git restore --staged <file>
# 从工作区和暂存区中删除文件
git rm <filename>
# 从工作区中移动或重命名一个文件、目录或symlink,并在完成后将变动更新至暂存区
git mv <filename>

2.提交快照至本地仓库

1
2
3
# 将暂存区文件提交至本地仓库
# 注:commit相当于为项目创建一个快照,它会在本地仓库生成一个commit对象储存相关快照信息,并更新它所指向的tree, blob对象,从而形成一个与commit快照对应的完整项目备份
git commit -m "message"

3.回退版本

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
### git reset ###
# 取消暂存区的所有变动,但是保留工作区变动
# 即,取消上次git commit后的所有git add操作
git reset HEAD
# 回到上一个版本
git reset HEAD^
# 回退至指定commit版本,并将HEAD指向这个commit版本
git reset <commit id>
# git reset 的行为模式
git reset --soft # 不修改暂存区和工作区的内容,只讲HEAD指向目标commit
git reset --mixed # [默认模式] 重置暂存区,不重置工作区
git reset --hard # 重置暂存区
# 对工作区的文件,恢复至目标commit的状态
# 即,未被其他commit保存的文件修改进度将丢失
git reset --merge # 重置暂存区
# 对工作区中的文件,如果其与暂存区和目标commit中均不相同,不会重置
# 即,某文件如果没有对应的git对象(即未备份或修改后未git add),不重置
git reset --keep # 重置暂存区
# 对工作区的文件,如果某文件与HEAD和目标commit都不相同,终止reset操作
# 即,某文件如果没有对应的git对象(即未备份或修改后未git add),终止操作

### git revert ###
# 撤销当前branch的上一次的commit对应操作
git revert
git commit -m "message about this revert"
# 注:
# 1. revert相当于用一个新的commit来抵消上一次commit做出的改变
# 2. revert操作导致HEAD指针在当前branch上前进;reset操作导致HEAD指针在当前branch上后退
# revert后的branch是:A->B->C => A->B->C->C'
# reset后的branch是:A->B->C => A->B
# 3. 因此在日后的merge操作时因为git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch时,导致这部分改变不会再次出现
# 下图示例中,f'是对f的revert操作(抵消了d e),因此对于最终合并得到的i,不会包含d e对应的变动
# master a -> b -> c -> f -> f' -> i
# \ / /
# dev d -> e -> g -> h
# 4. 但是git reset是之间把某些commit在某个branch上删除,因而和老的branch再次merge时,这些被回滚的commit应该还会被引入。
# 综上所述,git reset一般用于在本地中回滚版本;git revert则用于撤销已经push的操作,因为这样可以避免远程仓库的回滚和push --force命令的使用
# 撤销目标commit对应的操作
git revert <commit id>
git commit -m "message about this revert" # revert操作也需要对应的commit信息

4.检视命令

1
2
3
4
5
6
7
8
9
10
# 查看仓库当前状态,显示与HEAD指向的快照相比发生变化的文件
git status
# 比较工作区文件与暂存区文件的差异
git diff
# 比较工作区文件和某个commit快照的差异
git diff HEAD
git diff <branch name>
git diff <commit id>
# 查看commit的详细信息
git show <commit id>

同步管理

1.分支管理

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 branch
git branch -r # 查看远程分支
git branch -a # 查看本地分支以及远程分支
git brance -vv # 查看本地分支与远程分支的关联关系
# 创建分支
git branch <new branch> # 基于当前分支创建新分支
git branch <new branch> <origin branch> # 基于目标分支创建新分支
git branch <new branch> <repoName>/<origin branch> # 基于远程仓库的分支创建新分支
# 删除branch
git branch -d <branchName>
# 重命名分支
git branch -m <old branch> <new branch>
# 切换至目标分支
git checkout <branchName> # 切换至已有分支
git checkout -b <branchName> # 创建并切换至目标分支
git switch <branchName> # switch将来可能会替代checkout实现切换分支,且如果分支不存在会自动创建

# 检查远程仓库分支
git branch -r
# 同步远程仓库标签至本地
git remote update <repoName> -p* # 更新远程仓库分支列表
# 推送分支至远程仓库
git push <repoName> <local branch>:<repo branch> # 将本地<local branch>分支合并至远程的<repo branch>分支
git push origin --delete <branchName> # 删除远程仓库的<branchName>分支

2.标签管理

标签即一条分支上某个commit的别名,需要使用该commit id时均可以使用其对应的tag名作为替代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看所有标签
git tag
git tag -ln # 显示标签名以及描述信息
# 为目标commit创建标签
git tag <tagName> # 对当前指向的commit创建标签
git tag <tagName> <commit id>
# 删除本地标签
git tag -d <tagName>
# 切换至目标标签
git checkout <tagName>

# 推送标签至远程仓库
git push <repoName> <tagName> # 将本地目标tag推送至远程仓库
git push <repoName> --tags # 将本地所有tag推送至远程仓库
git push <repoName> :refs/tags/<tagName> # 在远程仓库删除目标标签

远程仓库管理

1.关联远程仓库

1
2
3
4
5
6
# 添加远程仓库,并命名为origin
git remote add origin <repo address>
# 重命名远程仓库
git remote rename <old> <new>
# 删除远程仓库
git remote add <repoName>

2.同步操作

拉取相关

1
2
3
4
5
6
7
8
9
10
11
12
# 以下操作中,均以origin指代远程仓库 
### fetch ###
# 从远程仓库获取代码库
git fetch <repoName>
### pull ###
# 注:
# pull命令其实就是先执行fetch命令获取目标远程分支信息,再与本地目标分支执行merge命令
git pull # 从远程仓库获取代码库,并将远程仓库的HEAD合并到本地HEAD
git pull <repoName> <branchName> # 远程<repo branchName>分支 合并至 本地当前分支
git pull <repoName> <repo branch>:<local branch> # 远程<repo branch>分支 合并至 本地<local branch>分支
git pull <repoName> <repo branch>:<local branch> --rebase # 即fetch结束后用rebase命令替换merge命令

推送相关

1
2
3
4
5
6
7
8
9
10
11
12
13
14
### push ###
# 将本地仓库HEAD合并到远程仓库的HEAD
git push origin master # 将本地master分支推送至远程master分支
git push <repoName> :<branchName> # 删除远程branchName分支
git push <repoName> <local branch>:<repo branch> # 将本地<local branch>分支合并至远程的<repo branch>分支
# -u用于设置默认主机
# 注:
# 如果当前分支与多个主机存在追踪关系,则可以使用-u选项指定一个默认主机,这样后面就可以不加任何参数使用git push
# 下面命令将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了
git push -u origin master
# 将本地所有分支都推送至远程仓库对应分支,如果没有对应分支,则创建对应分支
git push --all origin
# 强行推送至远程仓库
git push --force origin

冲突管理

1.合并分支-merge

1
2
3
4
5
6
7
8
9
# 合并分支
git merge <branchName>
# 注:
# git merge topic
# A---B---C topic
# / \
# D--E--F--G--(ABC)--H master(当前分支)
# 执行命令后,将在master分支上的G状态,重新按照A->B->C的顺序执行相应改动至G上
# 最终产生合并后的commit快照H

2.分支换基-rebase

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# git rebase命令可以将一个分支的基变更至另一个分支上
git rebase <branch for new base> <branch need rebase>
# 注:
# A---B---C <branch need rebase> feature
# /
# D--E--F--G <branch for new base> base
# 经过rebase后
# D--E--F--G(base)--A'--B'--C'(feature)
# 其原理是,将feature分支上的A B C逐个应用到base分支的G上
# 如果某一步出现冲突,就像merge一样手动解决冲突即可
# 当出现冲突或其他原因导致rebase操作暂停时,可以使用以下指令决定下一步操作
git rebase --continue | --skip | --abort | --quit | --edit-todo
# --continue 手动解决冲突后,执行该操作以将feature分支中下一个commit应用至base分支
# --skip 执行该操作以跳过feature分支中下一个commit的应用
# --abort

子仓库管理

1.添加子仓库

1
2
3
4
5
# 执行以下命令为当前工程添加子模块
git submodule add <仓库地址> <路径>
# <仓库地址> 是仓库的远程地址
# <路径> 是子模块要存放与当前仓库的目标路径
# 命令执行完成后,会在当前工程根路径下生成一个名为“.gitmodules”的文件,其中记录了子模块的信息。添加完成以后,再将子模块所在的文件夹添加到工程中即可。

2.删除子仓库

1
2
3
# 首先前往.gitmodules文件中删除相关子仓库的配置内容
# 再执行以下命令从git仓库删除子模块
git rm –cached

3.加载子仓库

1
2
# 当使用git clone下来的工程中带有submodule时,初始的时候,submodule的内容并不会自动下载下来的,需要执行下面命令加载
git submodule update --init --recursive

工作区常用git文件

.gitkeep文件

​ 由于git无法追踪空文件夹,需要在git中保留某空目录时,可以在目录下新建一个.gitkeep文件,保证git仓库不会忽略该空目录

.gitignore文件

​ 项目中许多临时生成的文件不需要被git仓库追踪,因此通过在某目录的.gitignore文件中写入规则,帮助git忽略对这个目录下某些命名方式文件的追踪,以下是示例语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# gitignore基本语法
# 用#表示注释
# 用*表示匹配0个或任意多个字符
# 生效范围是.gitignore文件所处目录下的所有子目录

# 忽略特定目录
/node_modules

# 忽略特定名称文件
config.ini # 忽略所有名为config.ini的文件
doc/*.txt # 忽略doc/notes.txt但不包括 doc/server/arch.txt
/TODO # 仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO

# 忽略特定后缀名的所有文件
*.log
*.o
!main.o # 表示main.o除外

# 忽略所有文件
!.gitkeep

# 注:
# push之后创建的.gitignore文件将不在生效

.gitattributes

参考: .gitattributes 作用详细讲解(git大佬必会技能)_StarJava_的博客-CSDN博客_gitattributes

​ gitattributes 是一个文本文件,文件中的一行定义一个路径的若干个属性,主要用于定义每种文件的属性,以方便 git 帮我们统一管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
### 基本格式 ###
# 匹配的文件模式 属性1 属性2 ...
### 可设置属性 ###
# text 视为文本文件
# -text 不视为文本文件
# eol=lf 行末字符(eol)为lf————入库时将行尾规范为LF(回车),检出时行尾不强制转换为CRLF(换行、回车)
# eol=crlf 行末字符(eol)为crlf入库时将行尾规范为LF(回车),检出时将行尾转换为CRLF(换行、回车)
# diff 强制视为文本文件,即使它包含一些通常从不会出现在文本文件的字节值,例如NUL
# !diff 表示为非文本文件,没有设置diff属性的路径会生成differ二进制文件(如果启用了二进制补丁,会生成二进制补丁)

### 常用语法 ###
# 定义js jsx json后缀名的文件,其
*.js eol=lf
*.jsx eol=lf
*.json eol=lf
# 对于txt后缀的文件,标记为文本文件
*.txt
# 对于sh后缀的文件,标记为文本文件,并规定其行末字符(eol)为lf
*.sh text eol=lf
# 对于vcproj后缀的文件,标记为文本文件,并规定其行末字符(eol)为crlf
*.vcproj text eol=crlf
# 对于jpg后缀的文件,标记为非文本文件
*.jpg -text