Git

一、概念

提交和分支

  • Git版本管理是通过提交(commit)组织起来的,每一个新的提交只记录产生变化的文件,所以存储开销不大。

  • 下文中的<ref>可以是分支(branch)、标签(tag)、提交号(CommitID)、HEAD或FETCH_HEAD等。其中branch、tag和FETCH_HEAD是指向某个提交的指针,它们的创建、删除和移动的开销很小。随着分支和提交的增多,提交历史形成了树状结构。

  • HEAD是当前所在分支的别名。如果分支名很长,可以用HEAD方便的表示当前分支。在一些自动化脚本里,HEAD也许会很有用。

  • 在某些修改发生后(例如git commit --amend),这个树状结构的某一条分支的最新的提交,没有被任何branch或tag指向,则这条分支将不会显示在提交历史中,但它在短时间内仍存在于仓库中,可以使用git reflog命令找到相关的提交,然后用git branch/checkout创建分支。

工作区和暂存区

  • 将每一个提交、工作区和暂存区分别视为一个版本,使用git status可查看暂存区版本和HEAD版本之间有差异的文件(Changes to be committed)、工作区版本和暂存区版本之间有差异的文件(Changes not staged for commit)。
  • 在分支没做任何修改的情况下,暂存区版本和HEAD版本保持一致,工作区版本和暂存区版本保持一致,所以git status结果以及VSCode的Git插件下不会显示内容。

  • 当对某文件做了修改,则工作区版本发生变化,工作区版本和暂存区版本就该文件不一致。

  • 然后使用git add将工作区文件版本刷新到暂存区,此时工作区版本和暂存区版本就该文件是一致的,而暂存区版本和HEAD版本就不再一致了。

  • git commit将暂存区版本加入到Git历史中,于是暂存区和HEAD再次一致。

远程仓库和远程分支

  • Git是分布式版本管理系统,每个仓库在Git系统中是平等的,一个仓库可以连接有多个远程仓库,它自己也可以作为其他仓库的远程仓库。

  • 位于本地仓库和远程仓库的分支在Git系统中也是平等的,只不过在开发中,人为地将远程仓库的分支作为稳定版本,而本地仓库的分支作为开发分支。之所以提这一条,是因为初学者往往把master分支和origin/master分支混淆起来,造成麻烦。

使用分支的策略

  • 如果无需连接远程仓库,设主干分支为master,一般新建dev分支开发,然后合入到master分支中。

  • 在多人协作开发中,主干分支一般为origin/master,在本地dev分支开发完后push到远程仓库的dev分支,然后创建合并请求合入到origin/master。


二、初始化仓库

git init

text 复制代码
git init <path>
    初始化文件夹为Git仓库。

git init
git init .
这两行等价

--bare 
    create a bare repository
    仓库将是bare仓库,不含工作区和暂存区。这种仓库可用作发布仓。

git clone

text 复制代码
git clone <repo> [<dir>]
    可用<dir>指定不同于仓库名的文件夹名。

-b, --branch=<branch>
    checkout <branch> instead of the remote's HEAD
    切换到指定分支,而不是远程仓库HEAD指向的分支。

--single-branch
    clone only one branch, HEAD or --branch
    仅拉取一个分支,HEAD指向的分支或者--branch指定的分支。

--depth=<depth>
    create a shallow clone of that depth
    仅拉取给定深度的提交历史,即拉取的历史提交和分支所在提交的距离不超过depth。

--bare
    create a bare repository

三、工作区和暂存区

git add

  • 功能:用工作区的文件刷新暂存区的文件。
  • 可以使用通配符,如git add *.c
  • .gitignore文件存放不用跟踪的文件;每个文件夹都可有此文件。更多规则参考忽略文件

git commit

  • 功能:提交暂存区版本。
  • 常用选项
text 复制代码
-m, --message <message>
    commit message

-C, --reuse-message <commit>
    reuse message from specified commit

-c, --reedit-message <commit>
    reuse and edit message from specified commit

--amend
    amend previous commit
    修订前一个提交,修改文件或提交信息。
    从另一个角度理解,实际上是把暂存区版本提交了,并将当前分支位置移动到新的提交上。

-a, --all
    commit all changed files
    提交前,先把工作区的修改文件都转到暂存区。
  • 在未使用-m-C等选项来指定提交信息时,将弹出默认编辑器来编辑提交信息。在纯终端环境,编辑器大概率是Vim类的终端文本编辑器。在Windows上可设置默认编辑器为VSCode。
bash 复制代码
git config --global core.editor "code --wait"

git restore

text 复制代码
git restore [--source=<ref>] [--staged] [--worktree] [--] <path>
    将文件恢复为指定版本。

--staged
    在未使用--staged选项时,操作工作区,指定后,操作暂存区。
    同时使用--staged和--worktree选项,则同时操作暂存区和工作区。

--source
    在未指定source选项时,对暂存区默认source是HEAD,对工作区默认source为是暂存区。
  • 因此下列命令可以理解为
text 复制代码
git restore <path>
    舍弃工作区的修改,即工作区版本和暂存区版本保证一致。

git restore <path> --staged
    舍弃暂存区的修改,即暂存区版本和HEAD版本保持一致,不影响工作区。

git restore <path> --staged --worktree
    舍弃暂存区和工作区的所有修改,即工作区版本和暂存区版本都和HEAD保持一致。
  • 下列命令也具有类似功能,但不建议使用。

checkout主要功能是切换分支,使用下列命令容易混淆。

text 复制代码
git checkout <ref> [--] <path>
    将工作区和暂存区都恢复为给定版本。
    等同于
    git restore --source=<ref> --staged --worktree [--] <path>

git checkout [--] <path>
    不指定<ref>时,仅操作工作区,使其和暂存区保持一致。
    等同于
    git restore <path>

git clean

git restore不会删除新增文件和忽略文件,这些文件可通过git clean删除。

text 复制代码
git clean <paths> --dry-run
    删除新增文件

-n, --dry-run
    dry run
    显示将要删除的文件列表,不会实际删除这些文件。

-f, --force
    force
    必须指定此选项才会删除

-d
    remove whole directories
    使用此选项才会递归文件夹

-e, --exclude <pattern>
    add <pattern> to ignore rules

-x
    remove ignored files, too
-X
    remove only ignored files
    有这两个选项,才会删除忽略文件,但是一般也不用,例如,'node_modules/'文件夹就是
    项目运行调试需要但不需要加入Git的文件夹。

git stash

当工作区或暂存区操作修改时切换分支,若有冲突,则切换失败,可将这些修改放入stash,然后切换分支。 (没怎么用这些命令行,一般使用GitLen插件)

text 复制代码
git stash push ...
    将更改放入stash

git stash list/show ...
    前者列出stash列表,后者列出一个stash的信息。

git stash branch ...	?

git stash pop/apply ...
    应用stash,前者将这个stash从stash列表中移除,后者不会。

git stash clear/drop ...
    前者删除全部stash,后者删一个。

git revert

(很少用)

text 复制代码
git revert <commitid> <commitid> ...
    在当前分支新建提交,这个提交会将commitid所做的变更取消。

四、分支

git branch

展示、创建、删除、重命名分支。

text 复制代码
git branch -vva	
    显示所有分支(包括远程仓库的分支)和分支的跟踪关系,*标记当前分支。

git branch <branch-name> [<ref>]
    在当前提交或给定提交<ref>处创建新分支,不切换到新分支。

git branch -d <branch-name>
    删除分支。

git branch -m <old> <new>
    重命名分支。

git checkout

切换分支。

text 复制代码
git checkout <ref>
    <ref>如果是CommitID/tag/带仓库名的远程分支,则将在ref创建临时无名分支,切出分支后不保留修改。
    如果希望保留修改,在临时分支上创建新分支即可。

git checkout -b <new-branch> <ref>
    在给定提交上创建新分支,并切换到新分支。如果<ref>是远程分支,还会设置跟踪关系。

git checkout -
    切回到上一个分支。

--orphan    
    创建一个新的分支,分支上没有任何提交,暂存区版本和HEAD版本内容相同。

git reset

重设分支位置,并且根据选项决定对工作区和暂存区的操作。HEAD是当前分支的别名,所以HEAD也会被重设。

text 复制代码
git reset [options] <refs>

--soft
    不重置工作区版本和暂存区版本,即不变。

--mixed
    不重置工作区版本,重置暂存区版本,

--hard
    同时重置工作区和暂存区版本,使其与重置后HEAD保持一致。即丢失所有修改。

使用--mix--hard可能导致丢失修改。

当<refs>为HEAD,将不会重设分支位置,命令效果和git restore相似。(前两条从没用过,第三条用得较多。)

text 复制代码
git reset --soft HEAD
    无任何作用。

git reset --mixed HEAD
    等同于
    git restore * --staged

git reset --hard HEAD
    等同于
    git restore * --staged --worktree

五、分支和提交

git merge

text 复制代码
git merge <ref> -m <message>
  • 如果当前分支是被合并分支的祖先,则会简单移动地当前分支。
  • 如果被合并分支是当前分支的祖先,则不变。
  • 如果位于两条支链上,将在当前分支创建新的提交把另一个分支(节点)内容合并到当前分支,可能需要解决冲突。
text 复制代码
git merge <ref1> <ref2> -m <message>
    一次可以合并多个分支。

--squash
    create a single commit instead of doing a merge
    不使用这个选项时,提交历史将保留合并关系,即是由哪些分支合并来的。
    使用这个选项,将仅创建新提交,提交历史成线性。这个选项适合被合并分支的
    提交历史过多或过于杂乱的情况。

--no-ff
    一个线性的提交历史上的两个分支,较老的分支合并较新的分支,在本地进行这
    样的操作时,将会fast forward,如果希望采用创建新提交的方式合并,则使用
    这个选项。

git rebase

text 复制代码
git rebase <ref>
  • 如果当前分支和是祖先关系,则同merge。
  • 如果位于两条支链上,则将共同祖先到当前分支的所有变更作用到另一个分支,并生成新的一系列提交,然后将当前分支重设到最新的提交上。当前分支原来的提交历史不保留,短时间内可用git reflog查看。
text 复制代码
git rebase --onto=<ref> <ref1>^ <ref2>
    将<ref1>到<ref2>的提交移植到以<ref>为起点。

git cherry-pick

text 复制代码
git cherry-pick <ref> ...
    将一个提交的更改应用到当前分支。

git cherry-pick <ref1>^..<ref>
    应用ref1到ref的修改到当前分支。

(未完待续)

相关推荐
bohu831 小时前
sentinel学习笔记5-资源指标数据统计
笔记·sentinel·statisticslot
璞~1 小时前
MQTT 课程概览 (学习笔记)02
笔记·学习
小王爱吃月亮糖2 小时前
C++进阶-1-单继承、多继承、虚继承
开发语言·c++·笔记·学习·visual studio
小王爱吃月亮糖2 小时前
补充--C++的项目结构和管理
数据结构·c++·笔记·学习
柳鲲鹏11 小时前
jiangdg/AndroidCamera关闭摄像头流程
笔记
warrah11 小时前
k8s迁移——岁月云实战笔记
笔记·容器·kubernetes
岳不谢13 小时前
华为DHCP高级配置学习笔记
网络·笔记·网络协议·学习·华为
19999er15 小时前
CDN信息收集(小迪网络安全笔记~
服务器·网络·笔记·安全·web安全
红色的山茶花16 小时前
YOLOv9-0.1部分代码阅读笔记-dataloaders.py
笔记·深度学习·yolo
UQI-LIUWJ16 小时前
datasets 笔记:加载数据集(基本操作)
笔记