【Git】Git常用命令

1、配置命令

# 查看全局配置列表
git config --global -l
# 查看局部配置列表
git config --local -l

# 查看所有的配置以及它们所在的文件
git config --list --show-origin

# 查看已设置的全局用户名/邮箱
git config --global --get user.name
git config --global --get user.email

# 设置全局用户名/邮箱
git config --global user.name "xiejiahe"
git config --global user.email "example@example.com"

# 设置本地当前工作区仓库用户名/邮箱
git config --local user.name "xiejiahe"
git config --local user.email "example@example.com"

# 删除配置
git config --unset --global user.name
git config --unset --global user.email

# 修改默认文本编辑器,比如 nano
# 常用编辑器:emacs / nano / vim / vi
git config --global core.editor nano

# 将默认差异化分析工具设置为 vimdiff
git config --global merge.tool vimdiff

# 编辑当前仓库配置文件
git config -e  # 等价 vi .git/config

# 文件权限的变动也会视为改动, 可通过以下配置忽略文件权限变动
git config core.fileMode false

# 文件大小写设为敏感, git默认是忽略大小写
git config --global core.ignorecase false

# 配置 git pull 时默认拉取所有子模块内容
git config submodule.recurse true

# 记住提交账号密码, 下次操作可免账号密码
git config --global credential.helper store # 永久
git config --global credential.helper cache # 临时,默认15分钟

2、命令别名配置

        git 可以使用别名来简化一些复杂命令,类似 alias 命令。

# git st 等价于 git status
git config --global alias.st status

# 如果之前添加过,需要添加 --replace-all 进行覆盖
git config --global --replace-all alias.st status

# 执行外部命令, 只要在前面加 ! 即可
git config --global alias.st '!echo hello';
# 加 "!" 可以执行外部命令执行一段复杂的合并代码过程,例如:
git config --global alias.mg '!git checkout develop && git pull && git merge master && git checkout -';

# 删除 st 别名
git config --global --unset alias.st

3、配置代理

# 设置
git config --global https.proxy  http://127.0.0.1:1087
git config --global http.proxy  http://127.0.0.1:1087

# 查看
git config --global --get http.proxy
git config --global --get https.proxy

# 取消代理
git config --global --unset http.proxy
git config --global --unset https.proxy

4、初始化仓库

        git init 创建一个空的Git仓库或重新初始化一个现有的仓库,实际上 git init 命令用得不多,通常在GUI上进行操作。

# 会在当前目录生成.git
git init

# 以安静模式创建,只会打印错误或警告信息
git init -q

# 在当前目录下创建一个裸仓库,里面只有 .git 下的所有文件
git init --bare

5、克隆

5.1、克隆仓库

# https 协议克隆
git clone https://github.com/xjh22222228/git-manual.git

# SSH 协议克隆
git clone git@github.com:xjh22222228/git-manual.git

# 克隆指定分支, -b 指定分支名字,实际上是克隆所有分支并切换到 develop 分支上
git clone -b develop https://github.com/xjh22222228/git-manual.git

# --single-branch 完全只克隆指定分支
git clone -b develop --single-branch https://github.com/xjh22222228/git-manual.git

# 指定克隆后的文件夹名称
git clone https://github.com/xjh22222228/git-manual.git git-study # 如果后面是 . 在当前目录创建

# 递归克隆,如果项目包含子模块就非常有用
git clone --recursive https://github.com/xjh22222228/git-manual.git

# 浅克隆, 克隆深度为1, 只克隆指定分支且历史记录只保留最后一条, 通常用于减少克隆时间和项目大小
git clone --depth=1 https://github.com/xjh22222228/git-manual.git
git clone --depth=1 --no-single-branch https://github.com/xjh22222228/git-manual.git # --no-single-branch 同时克隆其他所有分支


# 裸克隆, 没有工作区内容,不能进行提交修改,一般用于复制仓库
git clone --bare https://github.com/xjh22222228/git-manual.git

# 镜像克隆, 也是裸克隆, 区别于包含上游版本库注册
git clone --mirror https://github.com/xjh22222228/git-manual.git

5.2、克隆指定文件夹

        有些仓库会包含 客户端、服务端、等多个端的代码, 但又不想完整克隆整个项目, 只想克隆某个文件夹,这个时候就需要用到 稀疏检出。 开启稀疏检出必须满足2个条件:

  • core.sparsecheckout 设置为 true

  • .git/info/sparse-checkout 文件列出要检出的目录列表

# 1、创建一个目录并进入
mkdir hello-git && cd hello-git

# 2、初始化仓库
git init

# 3、设置仓库地址
git remote add origin https://github.com/xjh22222228/git-manual.git

# 4、开启稀疏检出功能
git config core.sparsecheckout true

# 5、编辑 .git/info/sparse-checkout 文件, 默认是没有需要手动新建
# 也可以通过命令将需要检出的目录路径写入追加进去
echo "media" >> .git/info/sparse-checkout

# 6、拉取内容, 这里指定的是 mater 分支
git pull origin master

6、管理仓库

        git remote 命令用来管理远程仓库。 通常一个项目对应多个仓库就需要用到 git remote, 比如要推送到 github / gitee / gitlab, 就可以用 git remote 来管理多个仓库地址。

# 查看远程仓库服务器, 一般打印 origin , 这是 Git 给你克隆的仓库服务器的默认名字
# 一般只会显示 origin , 除非你有多个远程仓库地址
git remote

# 指定-v, 查看当前远程仓库地址
git remote -v

# 添加远程仓库地址 example 是自定义名字
# 添加完后可以通过 git remote 就能看到 example
git remote add example https://github.com/xjh22222228/git-manual.git

# 查看指定远程仓库信息
git remote show example

# 重命名远程仓库
git remote rename oldName newName # git remote rename example simple

# 移除远程仓库
git remote remove example

# 修改远程仓库地址,从HTTPS更改为SSH
git remote set-url origin git@github.com:xjh22222228/git-manual.git

# 后续的推送可以指定仓库名字
git push example

7、暂存文件

# 暂存所有
git add -A

# 暂存某个文件
git add ./README.md

# 暂存当前目录所有改动文件
git add .

# 暂存一系列文件
git add 1.txt 2.txt ...

8、提交文件

# -m 提交的描述信息
git commit -m "changes log"

# 只提交某个文件
git commit README.md -m "message"

# 提交并显示diff变化
git commit -v

# 允许提交空消息,通常必须指定 -m 参数
git commit --allow-empty-message

# 重写上一次提交信息,确保当前工作区没有改动
git commit --amend -m "新的提交信息"

# 跳过验证, 如果使用了类似 husky 工具。
git commit --no-verify -m "Example" 

8.1、修改提交日期

        执行 git commitgit 会采用当前默认时间,但有时候想修改提交日期可以使用 --date 参数。

  • 格式:git commit --date="月 日 时间 年 +0800" -m "init"
  • 例子:git commit --date="Mar 7 21:05:20 2021 +0800" -m "init"

月份简写如下:

月份简写描述
Jan一月
Feb二月
Mar三月
Apr四月
May五月
Jun六月
Jul七月
Aug八月
Sep九月
Oct十月
Nov十一月
Dec十二月

9、推送远端

# 默认推送当前分支
# 等价于 git push origin, 实际上推送到一个叫 origin 默认仓库名字
git push

# 推送到主分支
git push -u origin master

# 本地分支推送到远程分支, 本地分支:远程分支
git push origin <branchName>:<branchName>

# 强制推送, --force 缩写
git push -f

10、查看分支

# 查看所有分支
git branch -a

# 查看本地分支
git branch

# 查看远端分支
git branch -r

# 查看本地分支所关联的远程分支
git branch -vv

# 查看本地 master 分支创建时间
git reflog show --date=iso master

# 搜索分支, 借助 grep 命令來搜索, 包含关键字 dev
git branch -a | grep dev

10.1、分支备注

        有时候分支过多很难通过分支名去判断这个分支做了什么。

# 命令
$ git config branch.{branch_name}.description 备注内容

# 给 hotfix/tip 分支添加备注信息
$ git config branch.hotfix/tip.description 修复细节

11、切换分支

# 切换到master分支
git checkout master

# 切换上一个分支
git checkout -

# 强制切换, 但是要小心,如果文件未保存修改会直接覆盖掉
git checkout -f master

# -t, 切换远端分支, 如果用了 git remote 添加一个新仓库就需要用 -t 进行切换
git checkout -t upstream/main

        在克隆时使用 `--depth=1` 切换其他分支,比如切换 dev 分支:

git clone --depth=1 https://github.com/xjh22222228/git-manual.git

# 切换 dev 分支
git remote set-branches origin 'dev'
git fetch --depth=1 origin dev
git checkout dev

        除了使用 git checkout 还有另一种方式切换那就是 git switch, 在Git版本 2.23 引入, 主要用于切换和创建分支。

# 切换到 develop 分支
git switch develop

# 切换到上一个分支
git switch -

# 强制切换到 develop 分支,并抛弃本地所有修改
git switch -f develop

# 创建分支并切换
git switch -c newBranch

# 强制创建分支
git switch -C newBranch

# 从前3次提交进行创建新的分支
git switch -c newBranch HEAD〜3 

# -t, 切换远端分支, 如果用了 git remote 添加一个新仓库就需要用 -t 进行切换
git switch -t upstream/main

12、创建分支

# 创建一个名为 develop 本地分支
git branch develop

# 强制创建分支, 不输出任何警告或信息
git branch -f develop

# 创建本地 develop 分支并切换
git checkout -b develop

# 创建远程分支, 实际上创建本地分支然后推送到远端
git checkout -b develop
git push origin develop

# 创建一个空的分支, 不继承父分支,历史记录是空的,一般至少需要执行4步
git checkout --orphan develop
git rm -rf .  # 这一步可选,如果你真的想创建一个没有任何文件的分支
git add -A && git commit -m "提交" # 添加并提交,否则分支是隐藏的 (执行这一步之前需要注意当前工作区必须保留一个文件,否则无法提交)
git push --set-upstream origin develop # 推送到远程

13、删除分支

        注意:删除分支不能删除当前分支,先切换到其他分支再删除。

# 删除本地分支
$ git branch -d <branchName>

# 大写 D 强制删除未完全合并的分支
# 等价 git branch --delete --force <branchName>
$ git branch -D <branchName>

# 删除远程分支
$ git push origin :<branchName>
$ git push origin --delete <branch-name>  # >= 1.7.0

14、重命名分支

# 重命名当前分支, 通常情况下需要执行3步
# 1、修改分支名称
# 2、删除远程旧分支
# 3、将重命名分支推送到远程
git branch -m <branchName>
git push origin :old_branch
git push -u origin new_branch


# 重命名指定分支
git branch -m old_branch new_branch

16、转移提交

        git cherry-pick 可以用来将一个分支的某次提交转移到当前分支中。 假设有 devmain 2个分支, dev 分支中有10次提交记录, main 分支想把 dev 的第5次提交记录合并到当前分支中, 这正是此命令的使用场景。 还可以理解为将以前的某次提交再重新提交一次。

# 可以是一个 commit_id 或者是分支名
# 如果是分支名则是最后一次提交
git cherry-pick <commit_id>|branch_name

# 支持转移多个提交, 会产生多个提交记录
git cherry-pick <commit_id1> <commit_id2>

# 保留原有作者信息进行提交
git cherry-pick -x <commit_id>

# 重新编辑提交信息, 否则会应用之前的commit消息
git cherry-pick -e <commit_id>

# 断开当前操作回到初始状态
git cherry-pick --abort

# 当发生冲突时解决冲突后使用 git add 加入到暂存区然后执行下面命令继续执行
git cherry-pick --continue

17、临时保存

        应用场景:假设当前分支某些功能做到一半了, 突然需要切换到其他分支修改Bug, 但是又不想提交(因为切换分支必须清理当前工作区,否则无法切换),这个时候 git stash 应用场景就来了。

# 保存当前修改工作区内容
git stash

# 保存时添加注释, 推荐使用此命令
git stash save "修改了#28 Bug"

# 保存包含没有被git追踪的文件
git stash -u

# 查看当前保存列表
git stash list

# 恢复修改工作区内容, 会从 git stash list 移除掉
git stash pop # 恢复最近一次保存内容到工作区, 默认会把暂存区的改动恢复到工作区
git stash pop stash@{1} # 恢复指定 id, 通过 git stash list 可查到
git stash pop --index # 恢复最近一次保存内容到工作区, 但如果是暂存区的内容同样恢复到暂存区

# 与 pop 命令一致, 唯一不同的是不会移除保存列表
git stash apply

# 清空所有保存
git stash clear

# 清空指定 stash id, 如果 drop 后面不指定id清除最近的一次
git stash drop stash@{0}
git stash drop  # 清除最近一次

# 查看已保存的修改文件内容
git stash show -p stash@{0}

18、文件状态

# 完整查看文件状态
git status

# 以短格式给出输出
git status -s

# 忽略子模块
git status --ignore-submodules

# 显示已忽略的文件
git status --ignored

19、日志

        查看历史日志可以通过 git log / git shortlog / git refloggit log 命令是3个最强大的命令:

# 查看完整历史提交记录
git log

# 查看前N次提交记录 commit message
git log -2

# 查看前N次提交记录,包括diff
git log -p -2

# 从 commit 进行搜索, 可以指定 -i 忽略大小写
git log -i --grep="fix: #28"

# 从工作目录搜索包含 alert(1) 这段代码何时引入
git log -S "alert(1)"

# 查看指定作者历史记录
git log --author=xjh22222228

# 查看某个文件的历史提交记录
git log README.md

# 只显示合并日志
git log --merges

# 以图形查看日志记录, --oneline 可选
git log --graph --oneline

# 以倒序查看历史记录
git log --reverse

git shortlog 以简短的形式输出日志, 通常用于统计贡献者代码量。

# 默认以贡献者分组进行输出
git shortlog

# 列出提交者代码贡献数量, 打印作者和贡献数量
git shortlog -sn

# 以提交贡献数量排序并打印出message
git shortlog -n

# 采用邮箱格式化的方式进行查看贡献度
git shortlog -e

        git reflog 通常被引用为 安全网,当 git log 没有想要的信息时可以尝试用 git reflog。当回滚某个版本时记录是不保存在 git log 中, 想要找到这条回滚版本信息时 git reflog 就用上了。

git reflog # 等价于 git log -g --abbrev-commit --pretty=oneline

20、变动查询

        git blame 用于查看某个文件的修改历史记录是哪个作者进行了改动。

# 查看 README.md 文件的修改历史记录,包括时间、作者以及内容
git blame README.md

# 查看谁改动了 README.md 文件的 11行-12行
git blame -L 11,12 README.md
git blame -L 11 README.md   # 查看第11行以后

# 显示完整的 hash 值
git blame -l README.md

# 显示修改的行数
git blame -n README.md

# 显示作者邮箱
git blame -e README.md

# 对参数进行一个组合查询
git blame -enl -L 11 README.md

21、合并

        feature/v1.0.0 分支代码合并到 develop:

git checkout develop
git merge feature/v1.0.0

        将上一个分支代码合并到当前分支:

git merge -

        以安静模式合并, 把develop分支合并到当前分支并不输出任何信息:

git merge develop -q

        合并不编辑信息, 跳过交互:

git merge develop --no-edit

        合并分支后不进行提交:

git merge develop --no-commit

        退出合并,恢复到合并之前的状态:

git merge --abort

        合并某个分支指定文件或目录, 需要注意的是这会直接覆盖现有文件,而不是本质上的合并。

# 将dev分支的 src/utils/http.js src/utils/load.js 2个文件合并到当前分支下
git checkout dev src/utils/http.js src/utils/load.js

22、删除文件

# 删除 1.txt 文件
git rm 1.txt

# 删除当前所有文件, 与rm -rf 命令不同的是不会删除 .git 目录
git rm -rf .

# 清除当前工作区缓存,但不会删除文件,通常用于修改文件名不生效问题
git rm -r --cached .

23、还原

        还原操作通过 git restore 命令。 git restore 是在 2.23 引入的, 是为了分离 git checkout / git reset 职责。

# 撤销工作区文件修改, 不包括新建文件
git restore README.md # 一个文件
git restore README.md README2.md # 多个文件
git restore . # 当前全部文件

# 从暂存区回到工作区
git restore --staged README.md

24、拉取命令

24.1、拉取远程分支最新内容

        默认情况下拉取当前分支

# 如果出现冲突会自动合并
git pull

24.2、拉取指定分支

# 远程分支名:本地分支名
git pull origin master:master
# 如果某个远程分支拉取并合并到当前分支后面可以省略
git pull origin master

24.3、拉取指定工作目录

# 默认情况下拉取会在当前工作目录中,但如果想拉取指定工作目录,可以指定 `-C`
git -C /opt/work pull

25、移动-重命名

        git mv 命令用来重命名文件或移动文件, 大部分开发者会选择手动进行移动文件, 手动和用 git mv 是有区别的。 手动和命令两者的区别(假设README.md重命名为README2.md):

  • 手动:先删除 README.md, 然后创建 README2.md, 历史记录无法正常追踪

  • git mv: 实际上是更新索引,把文件进行重命名, 可以通过历史记录方便检索

注意:新创建的文件不支持 git mv , 必须先提交。

# 将 1.txt 重命名为 2.txt
git mv 1.txt 2.txt

# 强制将 1.txt 重命名为 2.txt, 不管2.txt文件存不存在
git mv -f 1.txt 2.txt

# 移动目录也一样
git mv temp temp2

26、比较文件内容差异

        git diff 命令用于查看工作区文件内容与暂存区或远端之间的差异。

# 查看所有文件工作区与暂存区的差异
git diff

# 查看指定文件工作区与暂存区差异
git diff README.md

# 查看指定 commit 内容差异
git diff dce06bd

# 对比2个commit之间的差异
git diff e3848eb dce06bd

# 比较2个分支最新提交内容差异, develop分支与master分支, 如果没有差异返回空
git diff develop master

# 比较2个分支指定文件内容差异, develop 和 master READNE.md 文件差异
git diff develop master README.md README.md

# 查看工作区冲突文件差异
git diff --name-only --diff-filter=U

# 查看上一次修改了哪些文件
git diff --name-only HEAD~
git diff --name-only HEAD~~ # 前2次...

27、查看历史提交信息

# 不指定参数默认查看最新一条信息
git show

# 指定 commit_id 查看
git show d68a1ef

# 也可以指定 commit_id 查看指定文件提交信息
git show d68a1ef README.md

# 只指定文件名查看最后一次提交包含此文件的提交信息
git show README.md

# 指定分支名查看最后一次提交信息
git show feature/dev

28、回滚版本

回滚版本有2种方法:

  • git reset - 回滚版本后之前的历史记录将不保存, 不保留痕迹, 基本上不存在冲突情况。

  • git revert - 回滚版本后之前的历史记录还存在并多增加了一条 Revert 记录,很容易出现冲突。

git reset 命令用法:

# 回滚上一个版本
git reset --hard HEAD^

# 回滚上两个版本
git reset --hard HEAD^^

# 回滚到指定 commit_id , 通过 git log 查看
git reset --hard 'commit id'

# 回滚后但未推送到远程想断开当前操作执行拉取即可:
git pull

# 推送
git push -f

git revert 命令用法:

# 回滚上一次提交版本
git revert HEAD^

# 回滚指定commit
git revert 8efef3d37

# --no-edit 回滚并跳过编辑消息
git revert HEAD^ --no-edit

# 断开当前操作,还原初始状态
git revert --abort

# 推送到远程,假设当前是 main 分支
git push -u origin main

        回滚到指定分支或Commit_id指定文件, 命令:

#`git checkout [branch|commit_id] file file...`
$ git checkout main 1.txt 2.txt
$ git checkout 8efef3d37 1.txt 2.txt

29、撤销

# 撤销当前工作区所有文件的改动
git checkout -- .

# 撤销工作区指定文件改动
git checkout -- README.md

# 暂存区回到工作区
git reset HEAD^ # 上一次
git reset HEAD ./README.md # 指定 ./README.md 文件从暂存区回到工作区

# 指定commit回到工作区(前提是未推送到远程仓库), 需要还原的上一个commit_id
git reset <commit_id>

# 把某个commit_id还原初始状态 (前提是未推送到远程仓库), 需要还原的上一个commit_id
git reset --hard <commit_id>

30、标签

# 列出本地所有标签
git tag

# 列出远程所有标签
git ls-remote --tags origin

# 按照特定模式查找标签, `*` 模板搜索
git tag -l "v1.0.0*"

# 创建带有附注标签
git tag -a v1.1.0 -m "标签描述"

# 创建轻量标签, 不需要带任何参数
git tag v1.1.0

# 后期打标签, 假设之前忘记打标签了,可以通过git log查看commit id
git log
git tag -a v1.1.0 <commit_id>

# 推送到远程,默认只是本地创建
git push origin v1.1.0

# 一次性推送所有标签到远程
git push origin --tags

# 删除标签, 你需要再次运行 git push origin v1.1.0 才能删除远程标签
git tag -d v1.1.0

# 删除远程标签
git push origin --delete v1.1.0

# 检出标签
git checkout v1.1.0

# 查看本地某个标签详细信息
git show v1.1.0

31、变基

31.1、将多个 commit 合并为一条

        要注意保证当前工作区没内容再操作。

1、指定需要操作的记录,这时候会进入交互式命令

# start起点必填, end 可选,默认当前分支 HEAD 所指向的 commit
git rebase -i <start> <end>

git rebase -i HEAD~5 # 操作最近前5条提交记录
git rebase -i e88835de # 或者以 commit_id 进行操作
参数描述
p, pick保留当前commit,默认
r, reword保留当前commit,但编辑提交消息
e, edit保留当前commit,但停止修改
s, squash保留当前commit,但融入上一次提交
b, break在这里停止(稍后使用 git rebase --continue 继续重新设置基准)
d, drop删除当前commit

这里是倒序排列,最新的记录在最后

2、除了第一条后面全部改成 ssquash:

3、按 :wq 退出交互式,接着进入另一个交互式来编辑commit消息, 如果不需要修改之前的commit消息则直接退出:

4、强制推送到远端

# 推送到 main 分支
git push -u -f origin main

31.2、合并分支代码

        都说用 git rebase 代替 git merge 进行合并,这2个区别在于 git rebase 可以使历史记录更清晰, 下面2张图对比一下: 第一张图是 git rebase,第二张图是 git merge

        可以看出 git rebase 是一条直线的,git merge 则是各种交叉,很难理解。

        假设有2个分支,main 和 dev,下面使用 git rebase 将 dev 分支代码合并到 main 分支上。

# 1、先切换到 main 分支
git switch main

# 2、dev 分支合并到当前 main 分支
git rebase dev

# 没有冲突情况, 直接推送
git push

# 发生冲突情况,先解决完冲突 => 暂存 => 继续 => 强推
git add -A
git rebase --continue # 继续
git push -f # 强制推送

        中断 git rebase 操作, 如果操作一半不想继续使用 rebase 命令则可以中断此次操作。

$ git rebase --abort

32、工作流

        Git Flow 是一套基于git的工作流程,这个工作流程围绕着project的发布(release)定义了一个严格的如何建立分支的模型。git flow 只是简化了操作命令,不用 git flow 也可以,只要遵循 git flow 流程操作即可,手动一条一条命令执行也一样的。git flow 不是内置命令,需要单独安装。

32.1、初始化

        每个仓库都必须初始化一次才能使用,这是针对当前用户而言的。

# 通常直接回车以完成默认设置
git flow init

32.2、开始开发一个功能

        假设我们要开始开发一个新的功能比如登录注册,这个时候就要打一个 feature 分支进行独立开发。

# 步骤一:开启新的功能, 起一个分支名叫 v1.1.0, 建立后分支名为 feature/v1.1.0
git flow feature start v1.1.0

# 步骤二:将分支推送到远程, 在团队协作中这一步少不了
git flow feature publish v1.1.0

# 最后:完成功能, 会将当前分支合并到 develop 分支然后删除 feature/v1.1.0 分支,回到 develop
git flow feature finish v1.1.0

32.3、打补丁

        什么情况下需要打补丁? 假设已经上线的功能有BUG需要修复就需要打补丁了。 hotfix 是针对 master 分支进行打补丁的。

# 步骤一:开启一个补丁分支叫 fix_doc 用于修改文档错误,建立后分支名为 hotfix/fix_doc
git flow hotfix start fix_doc

# 步骤二:推送到远程,也可以不推,如果多人同时改BUG就需要推送共享分支
git flow hotfix publish fix_doc

# 最后:完成补丁, 将当前分支合并到 master 和 develop,然后删除分支,回到 develop
git flow hotfix finish fix_doc

32.4、发布

        假设产品给了个新需求并完成,这个时候可以选择发布。不发布也行,但是发布后会有版本区分,以后想找到某个版本的代码就很方便。

# 步骤一:建立一个发布版本 v1.1.0 建立后分支名为 release/v1.1.0
git flow release start v1.1.0

# 步骤二:推送到远程, 可选
git flow release publish v1.1.0

# 最后:将当前分支合并到 master 和 develop,打上一个标签,接着删除当前分支并回到 develop 分支上
git flow release finish v1.1.0

33、子模块

        git submodule 子模块的作用类似于包管理,类似 npm, 主要是复用仓库, 但比包管理使用起来更方便。

        子模块可以不建立版本分支管理代码, 因为它是依赖主应用,所以建立版本分支可以从主应用去操作,那么一旦建立新的版本分支当前的所有内容都会被锁定在这个分支上,不管子模块仓库怎么修改。

33.1、添加子模块

        添加完子模块后会发现根目录下多了个 .gitmodules 元数据文件,主要是用于管理子模块。

git submodule add https://github.com/xjh22222228/git-manual.git # 默认添加到当前目录下
git submodule add https://github.com/xjh22222228/git-manual.git submodules/git-manual  # 添加到指定目录

# -b 指定需要添加仓库的某个分支
git submodule add -b develop https://github.com/xjh22222228/git-manual.git

33.2、删除子模块

# 1、直接删除子模块目录
rm -rf submodule

# 2、编辑目录下的 .gitmodules 文件把需要删除的子模块删除掉

# 最后直接推送
git add -A
git commit -m "删除子模块"
git push

33.3、克隆一个包含子模块的仓库

# --recursive 用于递归克隆,否则子模块目录是空的
git clone --recursive https://github.com/xjh22222228/git-manual.git

# 如果已经克隆了一个包含子模块的项目,但忘记了 --recursive, 可以使用此命令 初始化、抓取并检出任何嵌套的子模块
git submodule update --init --recursive

33.4、修复子模块分支

        当把一个包含子模块的仓库克隆下来后会发现子模块分支不对,可以使用下面命令纠正:

git submodule foreach -q --recursive 'git checkout $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'

33.5、更新子模块代码

方法一:通常我们需要更新代码只需要执行 git pull, 这是比较笨的办法。

# 递归抓取子模块的所有更改,但不会更新子模块内容
git pull

# 这个时候需要进入子模块目录进行更新, 这样就完成了一个子模块更新,但是如果有很多子模块就比较麻烦了
cd git-manual && git pull

方法二:使用 git submodule update 更新子模块

# git 会尝试更新所有子模块, 如果只需要更新某个子模块只要在 --remote 后指定子模块名称
git submodule update --remote

# --recursive 会递归所有子模块, 包括子模块里的子模块
git submodule update --init --recursive

方法三:使用 git pull 更新, 这是一种新的更新模式,需要 >= 2.14

git pull --recurse-submodules

        如果嫌麻烦每次 git pull 都需要手动添加 --recurse-submodules,可以配置 git pull 的默认行为, 如何配置请参考 配置。具体使用还可以看这里 git submodule子模块使用教程

34、子树

        如果你知道 git submodule 那就大概知道 git subtree 干嘛用了, 基本上是做同一件事,复用仓库或复用代码。官方建议使用 git subtree 代替 git submodule

git subtree 优势:

  • 不会像子模块需要 .gitmodules 元数据文件管理

  • 子仓库会当做普通目录, 其实是没有仓库概念的

  • 支持较旧的Git版本(甚至比v1.5.2还要旧)。

  • 简单工作流程的管理很容易。

git subtree 劣势:

  • 命令过于复杂, 推送拉取都很麻烦

  • 虽然用于替代子模块, 但使用率并没有子模块广泛

  • 子仓库和主仓库混合在一起, 历史记录相当于有2个仓库的记录

git subtree add   --prefix=<prefix> <commit>
git subtree add   --prefix=<prefix> <repository> <ref>
git subtree pull  --prefix=<prefix> <repository> <ref>
git subtree push  --prefix=<prefix> <repository> <ref>
git subtree merge --prefix=<prefix> <commit>
git subtree split --prefix=<prefix> [OPTIONS] [<commit>]

注意:在操作 git subtree 时当前工作区必须清空,否则无法执行。

35、子仓库

35.1、添加子仓库

  • --prefix 指定将子仓库存储位置

  • main 是分支名称

  • --squash 通常做法是不将子仓库整个历史记录存储在主仓库中,如果需要的话可以忽略整个参数

        添加子仓库后, 会跟普通文件一样看待,可以进入 sub/common 目录执行 git remote -v 会发现没有仓库。

git subtree add --prefix=sub/common https://github.com/xjh22222228/git-manual.git main --squash

35.2、更新子仓库

        当远程子仓库有内容变更时,可以通过下面命令进行更新:

git subtree pull --prefix=sub/common https://github.com/xjh22222228/git-manual.git main --squash

35.3、推送子仓库

        假如修改了子仓库里的内容,可以将修改这部分的内容推送到子仓库中

# 需要先在主仓库把子仓库的代码暂存
git add sub/common
git commit -m "子仓库修改"
# 然后推送
git subtree push --prefix=sub/common https://github.com/xjh22222228/git-manual.git main --squash

36、切割

        随着项目的迭代, 主仓库会提交过多, 会发现每次 push 时会非常慢,尤其在 windows 平台较为明显。

        每次 push 到子仓库里头时会花费大量的时间来重新计算子仓库的提交。并且因为每次 push 都是重新计算的,所以本地仓库和远端仓库的提交总是不一样的,这会导致 git 无法解决可能的冲突。

        当使用 git split 命令后,使用 git subtree push,git 只会计算 split 后的新提交。

git subtree split --prefix=sub/common --branch=main

37、简化命令

        通过以上实操,不难发现,git subtree 太长了,每次操作都要敲这么长的命令,谁能忍得住。 将子仓库添加为远程仓库:

# common 是仓库名字,可以随意定义
git remote add -f common https://github.com/xjh22222228/git-manual.git

        要做其他 git subtree 命令时就不需要敲仓库地址了:

git subtree push --prefix=sub/common common main --squash

        虽然省去了仓库地址,命令还是太长。 还有另一种解决方案,就是使用别名,例如在 maclinux 中使用 alias 命令:

alias push="git subtree push --prefix=sub/common https://github.com/xjh22222228/git-manual.git main --squash"

        也可以使用 git 自带的别名命令 => 命令别名配置 ,如果你写前端,可以在 package.json 文件中加入:

{
  "scripts": {
    "push": "git subtree push --prefix=sub/common https://github.com/xjh22222228/git-manual.git main --squash"
  }
}

下次需要推送时执行:

npm run push 或者 yarn push

38、二分查找

        git bisect 基于二分查找算法, 用于定位引入Bug的commit,主要4个命令。 此命令非常实用, 如果你的Bug不知道是哪个 commit 引起的,可以尝试此方法。

# 开始
git bisect start [终点] [起点] # 通过 git log 确定起点和终点
git bisect start HEAD 4d83cf

# 记录这次的commit是好的
git bisect good

# 记录这次的commit是坏的
git bisect bad

# 退出
git bisect reset

39、归档

        创建一个归档文件,可以理解为将当前项目压缩为一个文件。会忽略掉 .git 目录。 但与 zip / tar 等压缩不同,git archive 支持将某个分支或commit进行归档。

参数描述
--format可选,指定格式,默认 tar, 支持 tar 和 zip,如果不填会根据 --output后缀格式进行推断
--output输出到指定目录
# 归档 master 分支 并打包在当前目录下 output.tar.gz
git archive --output "./output.tar.gz" master

# 归档指定commit
git archive --output "./output.tar.gz" d485a8ba9d2bcb5

# 归档为 zip, 无需指定 --format, 因为会根据文件后缀进行推断
git archive --output "./output.zip" master

# 归档一个或多个目录, 而不是归档整个项目
git archive --output "./output.zip" master src tests

40、格式化日志

        在使用 `git log` 命令时可以携带 `--pretty=format` 用来格式化日志。

参数描述
%H完整 commit hash
%h简写commit hash 一般是前7位
%T完整 hash 树
%t简写 hash 树
%an作者名称
%ae作者邮箱
%ad作者日期, RFC2822风格:Thu Jul 2 20:42:20 2020 +0800
%ar作者日期, 相对时间:2 days ago
%ai作者日期, ISO 8601-like风格: 2020-07-02 20:42:20 +0800
%aI作者日期, ISO 8601风格: 2020-07-02T20:42:20+08:00
%cn提交者名称
%ce提交者邮箱
%cd提交者日期,RFC2822风格:Thu Jul 2 20:42:20 2020 +0800
%cr提交者日期,相对时间:2 days ago
%ci提交者日期,ISO 8601-like风格: 2020-07-02 20:42:20 +0800
%cI提交者日期,ISO 8601风格: 2020-07-02T20:42:20+08:00
%d引用名称: (HEAD -> master, origin/master, origin/HEAD)
%D引用名称,不带 () 和 换行符: HEAD -> master, origin/master, origin/HEAD
%e编码方式
%B原始提交内容
%C自定义颜色
git log -n 1 --pretty=format:"%an" # xjh22222228

git log -n 1 --pretty=format:"%ae" # xjh22222228@gmail.com

git log -n 1 --pretty=format:"%d" #  (HEAD -> master, origin/master, origin/HEAD)

# 自定义输出颜色, %C后面跟着颜色名
git log --pretty=format:"%Cgreen 作者:%an"

41、清空 commit 历史

1、第一种方法原理是通过新建新的分支,假设要清空commit分支是 `develop`

# 1、新建一个新分支
git checkout --orphan new_branch
# 2、暂存所有文件并提交
git add -A && git commit -m "First commit"
# 3、删除本地 develop 分支
git branch -D develop
# 4、再将 new_branch 分支重命名为 develop
git branch -m develop
# 5、强制将 develop 分支推送到远程
git push -f origin develop

2、第二种方法通过更新 引用, 假设要重设 master 分支

# 通过 git log 找到第一个 commit_id
git update-ref refs/heads/master 9c3a31e68aa63641c7377f549edc01095a44c079

# 接着可以提交
git add .
git commit -m "第一个提交"
git push -f # 注意一定要强制推送

        这2种方法都是用于清空 commit 历史, 不会造成当前文件的丢失,所以放心。

42、提交规范

标志描述
feat该提交含有新的特性
style通常是代码格式的修改
chore构建过程或辅助工具的变动
fix修复Bug
docs文档修改
test单元测试改动
refactor代码重构
perf性能优化、体验
revert回滚版本
merge代码合并
typo错字, 比如单词拼错

43、冲突解决

        代码合并/更新代码 经常会遇到冲突的情况。解决冲突的流程如下:

  1. 执行 git pull 把代码拉下来,git 会自动尝试合并

  2. 编辑冲突文件, 根据实际情况保留本地代码还是远端代码

  3. 暂存文件并推送到远端

44、仓库迁移

        仓库迁移也可以叫复制仓库。 有时候需要从一个旧仓库迁移到新仓库,如果手动只能把文件进行迁移,但是如果需要把分支、标签、历史记录一起迁移就需要复制仓库。

1、克隆旧裸仓库

# 克隆裸仓库,里面没有工作区内容
git clone --bare https://github.com/xjh22222228/A.git

2、镜像推送至新仓库

cd A
git push --mirror https://github.com/xjh22222228/B.git

3、删除刚刚克隆的旧仓库

rm -rf A

4、拉取新仓库

git clone https://github.com/xjh22222228/B.git

除了通过命令迁移之外,可以通过网页导入仓库的方式也可以。

45、日志美化输出

# 1、全局配置
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
# 2、输入下面命令, 日志变得非常直观化
git lg

# 这里另外提供几种模式, 可以选择喜欢的一种进行别名配置
git config --global alias.lg "log --graph --pretty=format:'%Cred%h - %Cgreen[%an]%Creset -%C(yellow)%d%Creset %s %C(yellow)<%cr>%Creset' --abbrev-commit --date=relative"

git config --global alias.his "log --graph --decorate --oneline --pretty=format:'%Creset %s %C(magenta)in %Cred%h %C(magenta)commited by %Cgreen%cn %C(magenta)on %C(yellow) %cd %C(magenta)from %Creset %C(yellow)%d' --abbrev-commit --date=format:'%Y-%m-%d %H:%M:%S'"

git config --global alias.hist "log --graph --decorate --oneline --pretty=format:'%Cred%h - %C(bold white) %s %Creset %C(yellow)%d  %C(cyan) <%cd> %Creset %Cgreen(%cn)' --abbrev-commit --date=format:'%Y-%m-%d %H:%M:%S'"

46、生成 SSH Key

以下适用于 Mac / Linux

1、进入到 ssh

cd ~/.ssh

2、替换为您的GitHub电子邮件地址

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

3、当提示“输入要在其中保存密钥的文件”时,按Enter。接受默认文件位置。 (建议修改名字,防止以后被覆盖)

> Enter a file in which to save the key (/Users/you/.ssh/id_rsa): [Press enter]

4、在提示符下,键入一个安全密码, 默认回车即可

> Enter passphrase (empty for no passphrase): [Type a passphrase]
> Enter same passphrase again: [Type passphrase again]

5、生成的SSH Key 添加到 ssh config

vim ~/.ssh/config

# 粘贴
Host *
  IgnoreUnknown AddKeysToAgent,UseKeychain
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_rsa

最后将公钥添加到 Sign in to GitHub · GitHub 中

cat ~/.ssh/id_rsa.pub

47、记住密码

        使用 https 方式会要求每次都需要输入账号和密码,如果想下次不弹出账号密码可以按以下方式:

# 临时记住密码,默认15分钟
git config --global credential.helper cache

# 自定义记住密码时间,单位秒
git config credential.helper 'cache --timeout=3600'

# 长期记住密码
git config --global credential.helper store

48、清除账号

        清除git已保存的用户名和密码

# windows
git credential-manager uninstall

# mac / linux (以下任意一条命令都可)
git config --global credential.helper ""
git config --global --unset credential.helper

49、代理加速

在国内克隆或下载版本会很慢,可以借助下面镜像站点进行加速。

克隆:

# 公有仓库
git clone https://ghproxy.com/https://github.com/xjh22222228/git-manual.git

# 私有仓库, 需要配合Token使用 => https://github.com/settings/tokens
git clone https://user:your_token@ghproxy.com/https://github.com/your_name/your_private_repo

资源加速:

https://raw.githubusercontent.com/xjh22222228/git-manual/main/media/poster.png
# ↓ 替换为
https://cdn.jsdelivr.net/gh/xjh22222228/git-manual@main/media/poster.png

50、其它

# 查看git版本
git --version

# 清除本地git缓存
git rm -r --cached .

# 列出没有被 .gitignore 忽略的文件列表
git ls-files

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/574482.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

分布式文件系统--MinIO

1 MinIO安装(Docker) ●在root目录下新建docker_minio文件夹 ●在docker_minio文件夹下新建config文件夹,data文件夹 ●在root目录下新建docker_compose文件夹,在docker_compose文件夹中添加docker-compose.yaml services:minio:image: quay.io/minio/miniocontainer_name: mi…

新品发布!无人机装调检修实训系统

近年&#xff0c;我国密集出台相关产业政策&#xff0c;推动低空经济从探索走向发展&#xff0c;根据新华网数据&#xff0c;2030年低空经济规模有望达2万亿。无人机专业属于跨学科的综合性专业&#xff0c;其中装调检测技术是无人机教培的重要组成部分。 天途推出无人机装调检…

全额退款20000,what?

接单的时候有多兴奋&#xff0c;退单的时候就有多落寞。今天我对客户全额退款了&#xff0c;跟踪了10天的项目正式结束。 这是我接单以来项目单价最高的一个项目&#xff0c;本来不太想接的&#xff0c;因为业务领域不擅长&#xff0c;又想挑战一下。兜兜转转找了几个人因为各种…

19-ESP32-S3外设IIC

ESP32-S3的IIC 引言 ESP32-S3是一款集成了Wi-Fi和蓝牙功能的低成本、多功能微控制器。在这篇博客中&#xff0c;我们将详细介绍ESP32-S3的IIC&#xff08;Inter-Integrated Circuit&#xff09;接口&#xff0c;也被称为I2C。 IIC简介 IIC是一种串行、同步、多设备、半双工…

【机器学习】03. SMOTE算法实现数据集单个不平衡的样本扩充

背景&#xff1a;通常在处理分类问题中数据不平衡类别。使用SMOTE算法对其中的少数类别进行过采样&#xff0c;以使其与多数类别的样本数量相当或更接近。 直接上代码 from imblearn.over_sampling import SMOTE from sklearn.datasets import make_classification from colle…

openGauss学习笔记-271 openGauss性能调优-TPCC性能调优测试指导-测试MOT-TPCC性能

文章目录 openGauss学习笔记-271 openGauss性能调优-TPCC性能调优测试指导-测试MOT-TPCC性能271.1 TPC-C简介271.2 系统级优化271.3 BenchmarkSQL&#xff1a;开源TPC-C工具271.4 运行基准271.5 结果报告 openGauss学习笔记-271 openGauss性能调优-TPCC性能调优测试指导-测试MO…

AI智能写作工具,一键智能改写文章简单又高效

随着人们生活节奏的加快和工作压力的增大&#xff0c;如何在繁忙的日程中高效地写作成为了许多人的难题。但是随着人工智能技术的不断发展和应用&#xff0c;AI智能写作工具的出现&#xff0c;成为了许多人解决写作难题的利器。今天小编就来跟大家分享下AI智能写作工具&#xf…

自动驾驶行业源代码防泄漏解决方案

行业背景&#xff1a; 随着新一代信息通信及人工智能技术的快速发展&#xff0c;汽车作为这些新技术应用的重要载体&#xff0c;正在加速向智能化和网联化转型&#xff0c;以自动驾驶研发为主业的企业也越来越多&#xff0c;如何保障自己研发的算法、模型、系统不被研发人员离…

百度沈抖:智能,生成无限可能

4月16日&#xff0c;Create 2024百度AI开发者大会在深圳举行。会上&#xff0c;百度集团执行副总裁、百度智能云事业群总裁沈抖正式发布新一代智能计算操作系统——百度智能云万源。它能管理万卡规模的集群&#xff0c;极致地发挥GPU、CPU的性能&#xff1b;它有强大的大模型作…

创新科技赋能旅游服务:智慧文旅引领旅游发展新篇章,智能体验助力产业转型升级

随着科技的飞速发展和人们生活水平的提高&#xff0c;旅游业正迎来前所未有的发展机遇。创新科技在旅游服务领域的广泛应用&#xff0c;不仅提升了旅游体验的品质&#xff0c;也为旅游产业的转型升级注入了新的动力。智慧文旅作为旅游业与信息技术深度融合的产物&#xff0c;正…

【机器学习-12】数据探索---python主要的探索函数

在上一篇博客【机器学习】数据探索(Data Exploration)—数据质量和数据特征分析中&#xff0c;我们深入探讨了数据预处理的重要性&#xff0c;并介绍了诸如插值、数据归一化和主成分分析等关键技术。这些方法有助于我们清理数据中的噪声、消除异常值&#xff0c;以及降低数据的…

AI视频教程下载:用ChatGPT和 MERN 堆栈构建 SAAS 项目

这是一个关于 掌握ChatGPT 开发应用的全面课程&#xff0c;它将带领你进入 AI 驱动的 SAAS 项目的沉浸式世界。该课程旨在使你具备使用动态的 MERN 堆栈和无缝的 Stripe 集成来构建强大的 SAAS 平台所需的技能。 你将探索打造智能解决方案的艺术&#xff0c;深入研究 ChatGPT 的…

PM2管理器无法使用解决方法

之前的项目全是依靠PM2管理器部署的&#xff0c;部署快速&#xff0c;也便于管理 但是宝塔实在是bug毛病太多&#xff0c;最近这两天又出毛病了 这次的问题是在PM2管理器的node版本中无法进行版本切换&#xff0c;如果是第一次使用PM2的话甚至无法设置node版本&#xff0c;之前…

docker 集群管理实战mesos+zookeeper+marathon(一)

一 实验环境 1.1 系统版本&#xff0c;本实验使用cnetos7.9版本镜像 1.2 准备5台虚拟机&#xff0c;其中3台master&#xff0c;两台slave&#xff0c;使用克隆的方式 1.3 使用远程连接工具登录 1.4 修改主机名 1.5 设置域名映射 每个虚拟机都配置一下&#xff0c;这里就演示一…

区块链基础——区块链应用架构概览

目录 区块链应用架构概览&#xff1a; 1、区块链技术回顾 1.1、以太坊结点结构 1.2、多种应用场景 2、区块链应用架构概览 2.1、传统的Web2 应用程序架构 2.2、Web3 应用程序架构——最简架构 2.3、Web3 应用程序架构——前端web3.js ether.js 2.4、Web3 应用程序架构—…

浅谈菊风实时音视频 (RTC)与实时操作系统 (RTOS) 在智能硬件领域应用

近年来&#xff0c;菊风通过实时音视频赋能智能手表、智能门禁、智能门锁/门铃、智能眼镜等数十种智能硬件&#xff0c;与一众合作伙伴共同探索在IoT智能硬件领域的不同场景应用&#xff0c;积累了丰富的实践经验。在智能硬件中&#xff0c;RTOS因其轻量化的系统内核&#xff0…

C#基础之函数基础

函数 文章目录 1、函数基础1、概念2、函数位置3、基本语法4、实际运用5、return 2、ref 和 out1、ref 和 out 使用2、区别思考 登录 3、变长参数和参数默认值1、变长参数2、参数默认值 4、函数重载5、递归函数思考1 阶乘思考2 阶乘相加思考3 竹竿减半思考4 递归循环输出 1、函数…

多客圈子交友系统 uniapp+thinkphp6适配小程序/H5/app/api全开源,多款插件自选,支持个性定制!

网上交友的优点包括&#xff1a; 1. 方便&#xff1a;网上交友可以随时随地进行&#xff0c;不受时间和空间的限制&#xff0c;方便且高效。 2. 匿名性&#xff1a;网上交友可以实现匿名性&#xff0c;用户可以匿名地搜索、聊天或交换信息&#xff0c;保护个人隐私和安全。 3.…

RE | BUUCTF 刮开有奖1

题目&#xff1a;BUUCTF 刮开有奖1 参考&#xff1a; BUUCTF 刮开有奖&#xff08;特别详细了&#xff0c;尽自己全力理解所写&#xff09;&#xff08;这是主参考&#xff0c;写得很详细 BUUCTF_刮开有奖&#xff08;主参考的参考&#xff0c;思路很清晰 我是大菜鸡…尽力写自…

报错:图片验证码接口对接vue+springboot(下一个笔记会记录整个验证码的代码)

问题&#xff1a;空指针异常ai: 根据错误堆栈信息中提供的方法调用位置&#xff0c;看起来空指针异常是在 AuthCodeServiceImpl 类的 authUserCoded 方法的第 41 行发生的。 为了解决这个问题&#xff0c;你可以检查 AuthCodeServiceImpl 类中 authUserCoded 方法的第 41 行&am…
最新文章