目录
一. 本地操作
(1)git clone
// 1. 直接从远程clone,会在当前目录下创建一个名为 “libgit2” 的目录,并在这个目录下初始化一个 .git 文件夹
// git clone <url>
git clone https://github.com/libgit2/libgit2
// 2. 自定义目录名称,与上一条命令相同,但目标目录名变为了 mylibgit
git clone https://github.com/libgit2/libgit2 mylibgit
(2)git status
- 【基础命令】:git status
- 【紧凑的输出格式】:git status -s 或者 git status --short
- 新添加的未跟踪文件前面有 ?? 标记;新添加到暂存区中的文件前面有 A 标记;修改过的文件前面有 M 标记
(3)git diff
- status命令的输出非常简略,如果要显示具体修改了什么地方,需要借助diff名
- 【查看 当前文件 和 暂存区 的差异】:git diff
- 当前文件:包含未add的文件
- 暂存区:已add的文件,即已放入暂存区的文件
- 【查看 暂存区 和 最后一次提交的文件 的差异】:git diff --staged 或 git diff --cached
- 暂存区:已经add的文件
- 最后一次提交的文件:已经commit的文件
(4)git commit
- 【基础提交】:git commit -m "你的提交信息"
- 【越过add直接commit】:git commit -a
- 【补提交一些文件】:git commit --amend
- 例如,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作:最终你只会有一个提交——第二次提交将代替第一次提交的结果
- 修补提交最明显的价值是可以稍微改进你最后的提交,而不会让“啊,忘了添加一个文件”或 者 “小修补,修正笔误”这种提交信息弄乱你的仓库历史
-
git commit -m 'initial commit' git add forgotten_file git commit --amend
(5)git撤销操作
- 【回退到某个commit版本,commitId可以根据log指令查看】:git reset --hard commitId
- 情况1:把【文件状态2】变回【文件状态1】:git checkout -- xxx.java
- 情况2:把【文件状态3】变回【文件状态2】:git reset xxx.java
- 情况3:把【文件状态4】变回【文件状态3】:git reset --hard xxx.java
- 文件状态1:源文件a
- 文件状态2:源文件a添加了几行,但还未add
- 文件状态3:文件状态2 进行了add,加入了暂存区
- 文件状态4:文件状态3 进行了commit
- 所以,一整个撤销流程应该是这样的
-
git reset xxx.java //先把add的文件,取消add git checkout -- xxx.java //再把修改的文件,退回初始状态
-
(6)git rm
- 【删除文件,针对未add的文件】:git rm xxx.java
- 【强制删除文件,针对已add或commit的文件】:git rm -f xxx.java
- 【不删除文件,仅对文件取消git管理】:git rm --cached xxx.java
- 这种做法与在.gitgone中配置文件效果相同
(7)git mv
- 【为文件改名】:git mv 原文件名 新文件名
- 用idea工具的rename和这个没什么区别
- 相当于三步:先复制,删除原文件,添加新文件到git工作区
(8)git log
- 【基本命令】:git log
- 不传入任何参数的默认情况下,git log会按时间先后顺序列出所有的commit记录,最近的更新排在最上面
- 【带有详细修改信息,可以看到详细代码】:git log -p 或者 git log --patch
- 比较常用:可以清晰的看到每次commit的详细代码,用 up 和 down 键上下移动
- 也可以限制显示的日志条目数量,例如使用 -2 选项来只显示最近的两次提交:git log -p -2
- 【带有简略修改信息,每个文件的++--】:git log --stat
- 同样也可以限制日志条目数量,例如使用 -2 选项来只显示最近的两次提交:git log -stat -2
- 【自己设置详略信息,pretty参数】:git log --pretty:xxx
- xxx有四个选项:oneline, short, full, fuller
- 【超级简介,只显示一行】:git log --pretty:oneline
- 【效果等同于git log】git log --pretty:short
- 【会显示autor等】git log --pretty:full
- 【会显示autor, date等】git log --pretty:fuller
(9).gitignore文件
- 可以创建该文件,把一些文件忽略,规范如下
// 所有空行或者以 # 开头的行都会被 Git 忽略。
// • 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
// • 匹配模式可以以(/)开头防止递归。
// • 匹配模式可以以(/)结尾指定目录。
// • 要忽略指定模式以外的文件或目录,可以在模式前加上叹号(!)取反。
// 例子
# 忽略所有的 .a 文件
*.a
# 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a
# 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO
/TODO
# 忽略任何目录下名为 build 的文件夹
build/
# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt
# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdf
二. 远程操作
(1)git remote
- 【查看远程仓库信息】:git remote -v
-
- 【修改本地远程仓库的名称】:git remote rename 原来名称 新名称
- eg. git remote rename origin mybranch
- 一般clone下来的远程仓库,本地都会取默认名origin
- 【移除关联的远程仓库】:git remote remove 或 git remote rm
(2)git fetch
- 【拉取远程所有分支的信息到本地】:git fetch xx
- xxx是仓库的名称,可以用remote命令查看仓库名称,比如上面的origin
- 注意:这里拉取的是信息,拉取完后,本地将享有所有远程仓库的分支信息
- 【拉取远程所有分支】:git fetch <remote>
- 执行完成后,你将会拥有那个远程仓库中所有分支 的引用,可以随时合并或查看
(3)git push
- 【推送代码】:git push <remote> <branch>
- eg:git push origin feature/my_branch
- origin代表远程仓库名称,clone下来的仓库默认都是origin
- 【推送代码,但分支还未关联远程】:git push --set-upstream origin feature/123
(4)git branch 和 git checkout
- 【新建分支】
- 【指针还是停留在当前分支上】:git branch feature/xxx
- 【指针还是停留新分支上】:git checkout -b feature/xxx
- 本质为:git branch + git checkout
- 【切换分支,切换到feature/aaa上】:git checkout feature/aaa
- 【删除分支】:git branch -d feature/xxx
- 【强制删除】:有时候因为merge的原因删除会失败,可以使用-D强制删除:git branch -D feature/xxx
- 【查看当前分支和所有分支】:git branch
- 【查看当前分支和所有分支 + 外加commit信息】:git branch -v
-
- 【查看所有远程分支】:git branch -r
- 【过滤已经合并过的分支】:git branch --merged
- 下图例子表示:feature/20210923_leaf_opt为当前分支(因为前面有*),feature/20210916_isLimitSettled 和 master 的版本已经被 feature/20210923_leaf_opt 包含了,理论上可以删除分支名字前没有 * 号的分支
- 【过滤还未合并过的分支】:git branch --no-merged
(5)git merge
- 【合并分支,将feature/xxx分支合并到当前分支上】:git merge feature/xxx
- 【解决合并冲突】
- 合并时可能会存在冲突:可以用 git status 查看 unmerged 状态的文件,这些文件存在合并冲突
- 如何解决冲突:进入该文件,手动修改
-
- 【使用可视化工具,解决合并冲突】:git mergetool
- Git 使用 opendiff 做为默认的合并工具
(6)删除远程分支
- 【删除远程分支】:git push origin --delete feature/xxx
三. 配置相关
(1)配置别名(推荐使用)
- 例如:当要输入git commit时,只需要输入git ci
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
- 或者,可以把一长串命名,改成一小个单词
git config --global alias.unstage 'reset HEAD --'
//上面等价于,下面两个命令
git unstage fileA
git reset HEAD -- fileA
git config --global alias.last 'log -1 HEAD'
//通常也会添加一个 last 命令
git last
四. 原理相关
(1)存储原理
- 假设现在有一个工作目录,里面包含了三个将要被暂存和提交的文件
- 经过 add 和 commit 后:Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个 树 对象 (记录着目录结构和 blob 对象索引)以及一个 提交 对象(包含着指向前述树对象的指针和所有提交信息)
- 做些修改后再次提交,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针
(2)git文件状态
- 分成两类
- 已跟踪(被纳入了版本控制),再分三类
- 未修改
- 已修改
- 已放入暂存区
- 未跟踪
- 已跟踪(被纳入了版本控制),再分三类
五. 实践记录
- (1)本地版本回退 + 删除远程分支 + 重新上传分支
- git reset --hard hash :本地倒退到某个版本,git reset --hard edd3533200f
- git push origin --delete feature/xxxx:删除远程分支feature/xxxx
- git push:再推一次代码
- (2)拉取远程分支到本地
- git fetch origin 远程分支: eg. git fetch origin feature/xxxx