git 常用命令以及其他使用笔记

465 阅读5分钟

前言

  • 欢迎任何形式的转载,转载请保留原文链接:juejin.cn/post/684490…
  • 文章性质:非教程,意思是本文目的是便于使用时查阅,以及收集使用记录。所以看不明白的,请自行百度,这里不解释。当然欢迎指出存在的错误,以及新的用法
  • 文章主要内容:记录了使用 git 过程中的笔记,大部分为常用命令行记录。

目录

  • 前言
  • 推荐详细教程
  • 名词解释
  • Git 目录结构
  • Git 配置
  • 仓库创建
  • 仓库迁移/备份
  • 远程仓库操作
  • 本地仓库操作
    • 查看帮助
    • 项目添加、删除、提交
    • 对比
    • 日志
    • 版本管理
    • 分支管理
    • stash 管理
    • Tag 管理
  • git submodule
  • 添加 Git 忽略配置
  • 参考文献与版本同步

推荐详细教程

名词解释

  • 工作区(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

备注:

  1. origin:远程库名称
  2. master, deve, dev:是远程/本地分支名称,自定义
  3. 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

说明:

  1. 绿色表示文件被 git add,红色表示文件没有被 git add
  2. git diff -- readme.txt:其中 -- 作用是防止命令变成分支对比,如果不存在该分支,则可以省略 --,但不推荐
  3. deve:是分支名称,自定义
  4. 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"

官方语法说明

说明:

  1. 日志中 "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

说明:

  1. HEAD: 表示当前版本,HEAD^:表示上一个版本,HEAD^^:表示上上一个版本,HEAD~100:表示上上上...(100个上)个版本
  2. 版本号写前几位即可
  3. 版本穿梭后 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 ## 可以省略 --

说明:

  1. git checkout -- readme.txt:其中 -- 作用是防止命令变成分支切换,如果不存在该分支,则可以省略 --,但不推荐
  2. 误删回滚:无论是 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

备注说明:

  1. deve:是分支名称,自定义
  2. git branch:当前分支前面会标一个 * 号
  3. 切换分支:如暂存区不为空(即执行过 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

备注说明:

  1. --index 1:1 表示索引号,可通过 git stash list 查看
  2. git stash apply:不推荐,因为如果存在多个工作现场,则容易出现工作现场存在冲突的问题。推荐追加参数 --index
  3. git stash pop:不推荐,原因同上,不过一旦冲突,工作现场并不会自动删除。推荐追加参数 --index
  4. git 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

备注说明:

  1. v1.1.*、v1.1.0:标签名称,自定义
  2. 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 删除、重命名、修改仓库地址等操作,废弃本地仓库做法(不废弃本地仓库的做法见详细博客)

  1. 修改【.gitmodules】文件内容
  2. 提交修改并推送到远程仓库
  3. 重新 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 等内容