前言
- 欢迎任何形式的转载,转载请保留原文链接:juejin.cn/post/684490…
- 文章性质:非教程,意思是本文目的是便于使用时查阅,以及收集使用记录。所以看不明白的,请自行百度,这里不解释。当然欢迎指出存在的错误,以及新的用法
- 文章主要内容:记录了使用 git 过程中的笔记,大部分为常用命令行记录。
目录
- 前言
- 推荐详细教程
- 名词解释
- Git 目录结构
- Git 配置
- 仓库创建
- 仓库迁移/备份
- 远程仓库操作
- 本地仓库操作
- 查看帮助
- 项目添加、删除、提交
- 对比
- 日志
- 版本管理
- 分支管理
- stash 管理
- Tag 管理
- git submodule
- 添加 Git 忽略配置
- 参考文献与版本同步
推荐详细教程
- Git 官方资料
- Git 官方资料中文版,但不全是中文
- Git 官方资料中文翻译
- Git教程 - 廖雪峰的官方网站
- 初中高级的 git 和 gerrit 技巧【大型项目实战总结 && CR 经验】
- Git Submodule使用完整教程
名词解释
- 工作区(Working Directory):就是你在电脑里能看到的目录,不解释
- 版本库(Repository):就是 .git 目录
- 暂存区:命令
git add .就是将修改内容放置到暂存区,而命令git commit则是将暂存区的内容提交到当前分支
Git 目录结构
【项目目录】
- 【.gitignore】:忽略文件
- 【.gitmodules】:详见 git submodule 模块说明
【.git】 目录
- 【hooks/】:???
- 【info/】:???
- 【logs/】:???
- 【modules】:详见 git submodule 模块说明
- 【objects/】:这个就是项目的压缩对象(已提交的)
- 【refs/】:索引,包括 HEAD、remote、tag 等引用信息
- 【COMMIT_EDITMSG】:貌似是最后一次 commit 提交信息
- 【config】:配置信息,包括分支的索引信息以及绑定的远程分支、远程仓库信息等等
- 【description】:???
- 【FETCH_HEAD】:???
- 【HEAD】:当前分支的索引信息
- 【index】:好像是暂存区
- 【ORIG_HEAD】:???
- 【packed-refs】:???
Git 配置
配置保存在【~/.gitconfig】文件中
查看配置
git config --list
git config --global --list
配置用户信息
# 配置用户
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
# 查看用户
git config --global user.name
git config --global user.email
换行符 AutoCRLF 与 SafeCRLF
AutoCRLF
# 提交时转换为LF,检出时转换为CRLF
git config --global core.autocrlf true
# 提交时转换为LF,检出时不转换
git config --global core.autocrlf input
# 提交检出均不转换
git config --global core.autocrlf false
SafeCRLF
# 拒绝提交包含混合换行符的文件
git config --global core.safecrlf true
# 允许提交包含混合换行符的文件
git config --global core.safecrlf false
#提交包含混合换行符的文件时给出警告
git config --global core.safecrlf warn
建议
# 仅 Windows 开发环境
git config --global core.autocrlf true
git config --global core.safecrlf warn
# Windows、Linux 等混合开发环境(本博客作者表示怀疑)
git config --global core.autocrlf input
git config --global core.safecrlf warn
其他配置
# 设置[pretty]
git config --global pretty.graph '%C(auto)%h %C(green)%cd %C(bold blue)%cn %C(auto)%d%s'
# 设置别名:[alias]
git config --global alias.logg 'log --pretty=graph --date=short --graph --abbrev-commit'
# git status 显示中文
git config --global core.quotepath false
【.gitconfig】文件内容示例
[user]
name = Your Name
email = email@example.com
[core]
autocrlf = true
safecrlf = warn
仓库创建
# 建立本地仓库,效果生成【.git】目录与内容
git init
# 从远端克隆仓库(只会克隆默认分支,一般是 master)
git clone https://github.com/ReactiveX/RxJava.git
git clone https://github.com/ReactiveX/RxJava.git RxJava/
git clone ./rep.git
git clone ./rep.git rep/
# 从远端克隆仓库 非标准的ssh端口(非22)端口
git clone ssh://git@git.mobile.yljr.com:18211/android/android-yz.git
# 建立/克隆裸仓库
# 裸仓库:可以作为服务器仓库供各开发者 clone、pull、push 数据,实现数据共享和同步,不保存文件,只保存历史提交的版本信息
git init --bare
git init --bare --git-dir=rep.git
git clone --bare https://github.com/ReactiveX/RxJava.git
仓库迁移/备份
# 将 ReactiveX/RxJava.git 仓库迁移/备份到 xxx/RxJava.git 仓库
git clone --bare https://github.com/ReactiveX/RxJava.git
cd RxJava.git
git push --mirror https://github.com/xxx/RxJava.git
远程仓库操作
关联远程库
# 查看远程仓库信息
git remote -v
# 添加远程仓库
git remote add origin https://github.com/ReactiveX/RxJava.git
# 删除远程仓库的关联
git remote remove origin
# 重命名远程仓库名称
git remote rename origin newName
# 更换远程仓库地址
git config remote.origin.url https://github.com/ReactiveX/RxJava.git
远程分支管理:查看
# 查看本地和远程分支的详细信息
git branch -av
# 只查看远程分支的详细信息
git branch -rv
# 只查看本地分支的详细信息
git branch -v
# 更新远程分支列表
git remote update origin --prune
远程分支管理:拉取
# 从远程库更新到本地(不自动 merge)
git fetch
git fetch origin
git fetch origin master
# 从远程库更新到当前本地分支(自动 merge)
# git pull <远程库> <远程分支名>
git pull
git pull origin
git pull origin master
# 从远程库更新到指定本地分支(自动 merge)
# 错误做法:git pull <远程库> <远程分支名>:<本地分支名>,会导致当前分支被合并
# 拉取远程分支并创建本地分支
# git checkout -b 本地分支名称 远程库名称/远程库分支名称
git checkout -b dev origin/dev
git checkout --track origin/dev
# 拉取所有的远程分支
git branch -r | grep -v 'origin/HEAD' | while read remote; do git checkout --track ${remote##* }; done
远程分支管理:推送(影响远程库)
# 将本地分支推送到远程库,并自动关联本地分支与远程分支
# git push -u 远程库名称 本地分支名称:远程库分支名称
git push -u origin master:master
# 将本地分支推送到远程库,不关联本地分支与远程分支
git push origin master:master
git push origin master
# 将本地当前分支推送到远程库,当前分支与远程分支已关联才可使用
git push
远程分支管理:删除
# 删除远程分支
git push origin --delete dev
远程标签管理(影响远程库)
# 拉取远程标签到本地标签(指定)
git fetch origin tag v1.1.0
# 将本地标签推送到远程库(指定)
git push origin v1.1.0
# 将本地标签推送到远程库(所有)
git push origin --tags
# 删除远程库标签(指定)
git push origin :v1.1.0
# 其实不论是推送到远程,还是从远程库删除,命令均转换成以下语句,删除是源标签为空
# git push origin refs/tags/源标签:refs/tags/目的标签
git push origin refs/tags/v1.1.0:refs/tags/v1.1.0
备注:
- origin:远程库名称
- master, deve, dev:是远程/本地分支名称,自定义
- 1.1.0:本地标签名称,自定义
本地仓库操作
查看帮助
# 查看帮助
git help
git xxx help
项目添加、删除、提交
# 添加(内容更新到暂存区)
git add .
git add readme.txt
# 删除(内容更新到暂存区,同时删除工作区文件)
git rm readme.txt
# 提交
git commit -m "Wrote a readme file"
对比
状态对比
# 查看状态:当前代码库与最新版本的简单对比
git status
git status readme.txt
内容对比
# 工作区与暂存区对比
git diff -- readme.txt ## 有时可以省略 --,但不推荐,具体见下面的说明
# 工作区与版本区对比,HEAD 表示当前分支,deve 表示另一个指定分支的名称
git diff HEAD readme.txt
git diff HEAD -- readme.txt
git diff deve readme.txt
# 工作区与指定提交历史版本对比
git diff 1094a readme.txt
# 暂存区与版本区对比
git diff --cached
git diff HEAD ## ???
git diff --staged readme.txt
git diff --cached readme.txt
# 两个提交历史版本对比
git diff 574235 HEAD
git diff 1094a f574235
说明:
- 绿色表示文件被
git add,红色表示文件没有被git add git diff -- readme.txt:其中--作用是防止命令变成分支对比,如果不存在该分支,则可以省略--,但不推荐- deve:是分支名称,自定义
- 1094a、f574235:是版本号,就是 commit id
日志
# 查看项目 log
git log
# 查看详细日志
git log --stat
# 查看某文件 log
git log -- readme.txt
git log readme.txt
# 只查看 10 个 log
git log -10
# 一行显示 log,只显示哈希值和提交说明
git log --pretty=oneline
git log --oneline
# 查看图形日志
git log --oneline --graph --abbrev-commit
# 查看某文件每次提交的 Diff
git log -p readme.txt
# 查看某文件指定提交的 Diff
git show 1094a readme.txt # 1094a 是版本号,就是 commit id
自定义日志格式
# --graph:图形
# --date=format:%c:日期格式为 yyyy-MM-dd HH:mm:ss
# 内容:哈希值、提交时间、提交人、标签与分支标记、提交描述信息
git log --graph --date=format:%c --pretty=format:"%C(auto)%h %C(green)%cd %C(bold blue)%cn %C(auto)%d%s"
说明:
- 日志中 "HEAD —>" 当前版本指针,指向当前版本,以下简称 HEAD 指针
版本管理
版本库管理(可能会影响到工作区)
# 版本回滚(当前版本变为指定版本,同时暂存区被清空,不影响工作区)
git reset HEAD^
# 版本穿梭(当前版本变为指定版本,同时暂存区被清空,工作区的所有 modified 文件被 Revert 到指定版本)
git reset --hard HEAD^
git reset --hard 1094a # 1094a 是版本号,就是 commit id
# 查看版本管理命令历史,可用于获取所有的版本号
git reflog
git reflog show refs/stash # 只显示 stash
说明:
- HEAD: 表示当前版本,HEAD^:表示上一个版本,HEAD^^:表示上上一个版本,HEAD~100:表示上上上...(100个上)个版本
- 版本号写前几位即可
- 版本穿梭后
git log就只显示到指定版本,即不含指定版本之后的 log 信息
版本 Revert(不影响版本库)
# Revert 到暂存区(工作区与暂存区相同)
git checkout .
git checkout -- readme.txt ## 有时可以省略 --,但不推荐,具体见下面的说明
# Revert 到指定版本库(工作区与指定版本库相同,同时暂存区被清空)
git checkout HEAD^ .
git checkout HEAD^ readme.txt
git checkout HEAD^ -- readme.txt ## 可以省略 --
说明:
git checkout -- readme.txt:其中--作用是防止命令变成分支切换,如果不存在该分支,则可以省略--,但不推荐- 误删回滚:无论是
git rm,还是直接删除导致的误删,均可通过上述方式回滚
分支管理
# 查看分支,绿色标记的是当前分支
git branch -av
# 查看当前分支
git symbolic-ref --short -q HEAD
# 创建分支(不切换分支)
git branch deve
# 切换分支(注:-f,表示强制切换,会导致未提交的修改丢失)
git checkout deve
git checkout -f deve
git checkout -f 9198d00dd26d403b1d4e8dc137a33edc867f90c4
# 创建 + 切换分支
git checkout -b deve
# 删除分支
git branch -D deve
# 删除本地的远程分支(不影响远程仓库)
git branch -D -r origin/deve
# 合并指定分支到当前分支(Fast forward 模式,不保留分支信息)
git merge deve
# 合并指定分支到当前分支(推荐,禁用 Fast forward 模式,保留分支信息)
git merge --no-ff -m "add merge" deve
# 允许合并无关的分支,并保留各自的历史(一般用于合并两个仓库的情况)
git merge deve --allow-unrelated-histories
# 关联分支与远程分支
git branch --set-upstream-to origin/deve deve
# 查看指定分支最新提交的ID
git rev-parse refs/remotes/origin/deve
备注说明:
- deve:是分支名称,自定义
- git branch:当前分支前面会标一个 * 号
- 切换分支:如暂存区不为空(即执行过
git add),则需git commit或者git reset才能切换分支
stash 管理
实践表示不好用,原因是分支合并失败、切换失败的时候,也会创建 stash,容易混淆
# 当前工作现场存储起来,用于临时切换分支
git stash
git stash -u # 会把未跟踪的文件也存储起来
# 查看已存储的所有的工作现场信息
git stash list
git stash list --pretty=format:"%C(auto)%h %ad | %C(auto)%d%s %C(bold blue)<%an>" --abbrev-commit --date=format:"%Y-%m-%d %H:%M:%S"
# 查看工作现场文件状态信息
git stash show
git stash show --index 1
# 工作现场恢复(不删除工作现场)
git stash apply # 不推荐,具体原因见下面说明
git stash apply --index 1
# 删除工作现场(不推荐,具体原因见下面说明)
git stash drop # 不推荐,具体原因见下面说明
git stash drop --index 1
# 工作现场恢复(自动删除工作现场)
git stash pop # 不推荐,具体原因见下面说明
git stash pop --index 1
备注说明:
--index 1:1 表示索引号,可通过git stash list查看git stash apply:不推荐,因为如果存在多个工作现场,则容易出现工作现场存在冲突的问题。推荐追加参数--indexgit stash pop:不推荐,原因同上,不过一旦冲突,工作现场并不会自动删除。推荐追加参数--indexgit stash drop:不推荐,容易造成误删除,因为该命令删除的是索引号为 0 的工作现场(并不管该工作现场是哪个分支的)。推荐追加参数--index
Tag 管理
# 列显已有的标签(按字母顺序排列)
git tag
# 列显已有的标签(检索模式)
git tag -l 'v1.1.*'
# 新建标签(轻量级标签:指向特定提交对象的引用)
git tag v1.1.0
# 新建标签(含附注的标签:独立对象,有自身的校验和信息)
git tag -a v1.1.0 -m 'my version 1.1.0'
# 新建标签(签署标签:含附注的标签的一种)
git tag -s v1.1.0 -m 'my signed 1.1.0 tag'
# 后期向某次提交加注标签
git tag -a v1.2 9fceb02
# 删除标签
git tag -d v1.1.0
# 验证标签
git tag -v v1.1.0
# 切换标签(切换到一个名为'(HEAD detached at v1.1.0)'的空白分支上)
git checkout v1.1.0
备注说明:
- v1.1.*、v1.1.0:标签名称,自定义
- 9fceb02:某次 commit 信息,自定义
译注:
- -a:取 annotated 的首字母
- -s:取 signed 的首字母
- -v:取 verify 的首字母
git submodule
# 查看 submodules
# 结果的 hash 前不带符号说明该 module 正常且提交版本同步(提交版本同步指主项目记录提交版本与子模块当前提交版本一致)
# 结果的 hash 前带 - 号说明该 module 未初始化
# 结果的 hash 前带 + 号说明该 module 版本未同步
git submodule
git submodule status
# 初始化 modules,重复初始化无影响,例子中后跟 rxjava 为指定初始化某个 module 的名称(下同)
git submodule init
git submodule init rxjava
# 版本未同步时,检出 modules,保证检出的版本与主项目匹配,但子 module 会创建临时分支
git submodule update
git submodule update rxjava
# 添加 submodule,例子中后跟 rxjava 为该 module 名称与目录名
git submodule add https://github.com/ReactiveX/RxJava.git
git submodule add https://github.com/ReactiveX/RxJava.git rxjava
# 强制添加 submodule(仅用于 git submodule 没有正确的显示某个 module)
git submodule add --force --name rxjava https://github.com/ReactiveX/RxJava.git
# 遍历所有 submodule 执行指定命令
# git submodule foreach 其他命令,如:
git submodule foreach git pull
git submodule foreach ls -l
复合命令
# 重新 clone 项目(含 clone 所有子项目)方式一
git clone --recursive https://github.com/ReactiveX/RxJava.git
# 重新 clone 项目(含 clone 所有子项目)方式二,依次执行以下命令
git clone https://github.com/ReactiveX/RxJava.git
git submodule init
git submodule update
# pull 项目,并检出新增 submodule
git pull
git submodule init
git submodule update [submodule 名称]
# pull 项目,并移除废弃 submodule
# 建议重新 clone 项目
# pull 项目,并重命名 submodule
# 建议重新 clone 项目
详细说明见博客《Git Submodule 命令使用与详细教程》:juejin.cn/post/694825…
submodule 删除、重命名、修改仓库地址等操作,废弃本地仓库做法(不废弃本地仓库的做法见详细博客)
- 修改【.gitmodules】文件内容
- 提交修改并推送到远程仓库
- 重新 clone 仓库
仓库迁移
从远程仓库获取所有分支,会让所有分支都会关联到远程分支
git clone xxx
git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done
git fetch --all
git pull --all
git branch -avv # 查看分支是否关联正确,关联不正确的分支无法 git pull
#!/bin/sh
if [ -z $1 ]; then
echo '请输入 git clone 的地址'
return -1
fi
dir=$2
if [ -z $dir ]; then
url=$1
dir=${url##*/}
dir=${dir%%.*}
fi
git clone $1 $2
cd $dir
git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done
git fetch --all
git pull --all
git branch -avv # 查看分支是否关联正确,关联不正确的分支无法 git pull
推送所有分支到远程上,会让所有分支都会关联到远程分支
git push --all origin -u
# 或
git push --mirror
添加 Git 忽略配置
由目录下的[.gitignore]文件确定,使用规则如下:
通配符:
- / :表示目录
- * :匹配多个字符
- ? :匹配单个字符
- ! :包含单个字符的匹配列表
- [] :表示不忽略(跟踪)匹配到的文件或目录
详细说明:
- 一行一个忽略项
- 配置按从上到下进行规则匹配的,意味着如果前面的规则匹配的范围更大,则后面的规则将不会生效
- 规则【build/*】: 等同于【build】,忽略根目录或某一目录下的[build],以及其下的全部内容
- 规则【/.idea/*】: 等同于【/idea】,忽略根目录下的[.idea],以及其下的全部内容
- 以下规则,表示忽略全部内容,但是不忽略[.gitignore]文件
/* !.gitignore
参考文献与版本同步
参考文献:
- 见《推荐详细教程》章节
博客同步版本:
- 2018-05-30:首发博客
- 2022-04-28:同步 git submodule 等内容