Git 笔记
本文为个人自用 Git 笔记,记录了 Git 的常用命令,不定时更新(●’◡’●)。
Git 常用命令
clone
基本格式为:
git clone [url] [directory]
,其中[directory]
表示需要创建目录的本地名称,省略则默认为版本库的名称。
有一些附加参数如下
-l | --local
:只有当指定的版本库是一个本地路径才会生效,能跳过正常的传输机制,直接复制.git
目录下的部分文件,即使不指定这个选项默认也会采用本地优化,但注意由于硬链接的特性,本地优化的克隆方式存在一些风险。-s | --shared
:当远程版本库在本地机器上时,使用这个选项可以让本地版本库与远程版本库共享对象文件,而不是复制或链接。--depth <depth>
:使用这个选项可以创建一个浅克隆,即只获取最近的<depth>
个提交,而不是整个历史记录。这样可以节省时间和空间。--single-branch
:使用这个选项可以只克隆远程版本库的一个分支,而不是所有分支,来节省克隆时间。默认情况下,这个分支是当前活动分支。
add
基本格式为:
git add [file1] [file2] …
,其中file
为文件名称。
有一些附加参数如下
-u
:只会添加已经被跟踪的文件,也就是说,它会将修改过或删除过的文件添加到暂存区,但是不会添加新文件。-A
:会添加所有的文件,包括修改过、删除过和新建的文件。
commit
基本格式为:
git commit [file1] [file2] … -m 'msg'
,没有file
文件默认为全部提交。
branch
基本格式为:
git branch <branchname>
,创建一个新的分支。有一些附加参数如下
-a
:显示本地分支和远程分支。-m | -M
:重命名当前分支,-M
为强制重命名,即使名称已存在会强制覆盖掉分支名称。-d | -D
:删除分支,-D
强制删除。-v | -vv
:显示本地分支最后一次提交记录,-vv
显示本地分支与远程分支的关联。
status
基本格式为:
git status
merge
基本格式为:
git merge <branchname>
。
快速合并的时候是不会生成提交记录的
TIP:
最新提交是合并提交,那么它有两个父提交,分别是合并前的两个分支的最新提交。当你用git reset --hard HEAD^
回退时,你其实是回退到合并提交的第一个父提交,也就是当前分支合并前的最新提交。这样你就会丢失合并提交和另一个分支的所有修改。如果你想回退到合并提交的第二个父提交,也就是另一个分支合并前的最新提交,你可以用git reset --hard HEAD^2
,其中2
表示第二个父提交。
rebase
Git rebase
是一种变基操作,它可以将一个分支的提交重新应用到另一个分支上,从而使两个分支的历史线性化。Git rebase
的好处是可以保持提交历史的清晰和简洁,避免不必要的合并提交。但是,Git rebase
也有一些缺点,其中之一就是可能会产生冲突。
Git rebase
的基本用法是:
这个命令的意思是,将 <target-branch>
分支变基到 <base-branch>
分支上。也就是说,将 <target-branch>
分支上的提交,重新应用到 <base-branch>
分支的最新提交之后,从而使 <target-branch>
分支的历史成为 <base-branch>
分支的直接后继。
例如,假设有两个分支 master
和 dev
,它们的提交历史如下:
其中,A、B、C、D、E、F
都是提交 ID
的简写,A
是最早的提交,F
是最新的提交。如果我们想要将 dev
分支变基到 master
分支上,也就是说,我们想要将 E
和 F
这两个提交重新应用到 master
分支的最新提交 D
上,从而使 dev
分支的历史线性化,我们可以在 dev
分支上执行以下命令:
或者,我们可以先切换到 dev
分支,然后执行:
这样,dev
分支的提交历史就变成了:
这里,E'
和 F'
是 E
和 F
的副本,它们的内容和 E
和 F
相同,但是它们的提交 ID
不同,因为它们是在 D
的基础上重新生成的。这样,dev
分支就变成了 master
分支的直接后继,它们的历史线性化了。
但是,如果在 master
分支上的 C
和 D
这两个提交,和 dev
分支上的 E
和 F
这两个提交,都对同一个文件的同一行内容做了不同的修改,那么在执行 git rebase master
时,就会发生冲突。例如,假设在 master
分支上的 C
提交,修改了文件 file.txt
的第 10
行,将原来的内容 "Hello World"
改成了 “Hello Git"
,而在 dev
分支上的 E
提交,也修改了文件 file.txt
的第 10
行,将原来的内容 "Hello World"
改成了 "Hello Bing"
。那么当 Git
尝试将 E
提交应用到 D
上时,就会遇到冲突,因为 Git
不知道要保留哪个版本的内容。这时候,Git
会在 file.txt
的第 10
行,用特殊的符号标记出冲突的部分,如下所示:
这里,HEAD
表示目标分支的最新提交,也就是 D
,E
表示正在应用的提交,也就是 E
。Git
会中断变基的过程,让你手动解决冲突,你可以选择保留其中一个版本的内容,或者合并两个版本的内容,或者删除整个内容,然后保存文件,执行 git add file.txt
命令,将文件标记为已解决冲突,再执行 git rebase --continue
命令,继续变基的过程。如果你没有冲突需要解决,或者你想放弃变基的操作,你可以执行 git rebase --abort
命令,回到变基之前的状态。如果你想跳过某个提交,不将它应用到目标分支上,你可以执行 git rebase --skip
命令,继续变基的过程。
当你解决完所有的冲突后,Git
会将 dev
分支的指针移动到最新的提交上,也就是 F'
,这样,dev
分支就变成了 master
分支的直接后继,它们的历史线性化了。但是,你要注意,dev
分支的提交记录已经被重写了,它的提交 ID
和提交顺序都可能发生了变化,这可能会影响你和其他人的工作,所以在使用 Git rebase
时,要谨慎操作,并且与团队成员保持沟通。
Git rebase
还有一些高级用法,例如交互式变基,它可以让你修改、重排、合并、拆分、删除或者重新编写你的提交记录。你可以使用 git rebase -i <base-branch>
命令来启动交互式变基,它会打开一个文本编辑器,让你选择你想要执行的操作。
switch
git switch
相比与git checkout
而言更注重于分支操作,而不会用于恢复文件
基本格式为:git switch <branchname
。
常用命令:
- 切换到已存在的分支:
git switch <branch>
- 创建并切换到新的分支:
git switch -c <new-branch> [<start-point>]
- 从任意分支分离工作树:
git switch --detach [<start-point>]
- 创建并切换到孤儿分支:
git switch --orphan <new-branch>
- 切换到上一次切换的分支:
git switch -
其中,<branch>
是要切换到的分支名,<new-branch>
是要创建的新分支名,<start-point>
是新分支的起始点,可以是一个提交或者另一个分支。如果省略<start-point>
,则默认为当前 HEAD 所指向的位置。
restore
将文件恢复到最近一次提交的状态
基本格式为:git restore <file>
log
用于显示日志提交信息
基本格式为git log
进入git log
界面后的操作
- 空格键:向下滚动一屏幕的内容
- 回车键:向下滚动一行的内容
b
键:向上滚动一屏幕的内容k
键:向上滚动一行的内容q
键:退出git log
界面
fetch
从远程仓库获取数据但不会自动合并
基本用法为:git fetch <remote>
- 从默认的远程仓库获取数据:
git fetch
- 从指定的远程仓库获取数据:
git fetch <remote>
- 从指定的远程仓库和分支获取数据:
git fetch <remote> <branch>
- 从指定的远程仓库和分支获取数据并更新本地分支:
git fetch <remote> <branch>:<branch>
- 从所有配置的远程仓库获取数据:
git fetch --all
push
将本地的提交向远程库推送
基本格式为:git push <remote> <branch>
pull
从远程库获取数据并合并
基本格式为:git pull <remote> <branch>
checkout
用于切换分支、恢复文件或检出提交。
基本格式为:git checkout <branch>
reset
用于将当前的
HEAD
复位到指定状态
基本格式为:git reset --[option] <commit>
有三个选项
mixed
:将文件回退到工作区,此时会保留工作区中的文件,但会丢弃暂存区中的文件。soft
:将文件回退到暂存区,此时会保留工作区和暂存区中的文件。hard
:将文件回退到修改前,此时会丢弃工作区和暂存区中的文件。
当版本不同的时候,更改会存放在工作区或者暂存区。
revert
用于创建一次新的提交来回滚版本
基本格式为:git revert <commit>
stash
该命令用于将当前工作目录中的临时更改保存到一个栈中,以便你可以切换到其他分支或提交上继续工作,注意新建的文件不会被
stash
暂存,需要全部add
到工作区或者加上-u
参数,另外当所有文件都在暂存区的话,pop
之后新文件会放到暂存区,而修改的文件放在工作区。
基本格式为:git stash
remote
用于对远程库进行操作
cherry-pick
基本格式为
git cherry-pick <commitHash>
git cherry-pick <commitHash>
:将某一提交应用到当前分支。git cherry-pick <branchname>
:将某一分支的最新提交应用到当前分支git cherry-pick <HashA> <HashB>
:将多个提交应用到当前分支选项:
-x
:在提交信息的末尾追加一行(cherry picked from commit ...)
,方便以后查到这个提交是如何产生的。-s,--signoff
:在提交信息的末尾追加一行操作者的签名,表示是谁进行了这个操作。
tag
Git
的tag
有两种类型:轻量标签(lightweight
)和含附注的标签(annotated
)。轻量标签就是一个指向特定提交的引用,它不会存储任何额外的信息。含附注标签是存储在 Git 数据库中的一个完整对象,它有一个标签名,标签信息,标签签名等信息。一般我们都建议使用含附注型的标签,以便保留相关信息;当然,如果只是临时性加注标签,或者不需要旁注额外信息,用轻量标签也没问题。
Git
的tag
的使用方法如下:
- 创建轻量标签的命令如下:
git tag <tag_name> <commit_id>
,其中<tag_name>
是标签的名称,<commit_id>
是要标记的提交的 ID,如果省略<commit_id>
,默认>会使用当前所在分支的最新提交作为标签指向的提交。- 创建含附注标签的命令如下:
git tag -a <tag_name> -m "<tag_message>" <commit_id>
,其中-a
选项表示创建一个带注解的标签,-m
选项表示添加标签的信息,<tag_message>
是标签的描述,<commit_id>
是要标记的提交的 ID,如果省略<commit_id>
,默认会使用当前所在分支的最新提交作为标签指向的提交。- 查看当前项目中的所有标签,可以使用以下命令:
git tag
,如果想查看某个具体标签的信息,可以使用以下命令:git show <tag_name>
。- 推送标签到远程服务器,可以使用以下命令:
git push origin <tag_name>
,如果要一次性推送所有本地标签,可以使用以下命令:git push origin --tags
。- 删除本地标签的命令如下:
git tag -d <tag_name>
,删除远程标签的命令如下:git push origin :refs/tags/<tag_name>
。
Git 使用技巧
查看本地分支与远程分支的关联
将本地分支与远程分支关联
如何回退版本
git reset --hard HEAD^
git revert HEAD
git checkout commit_id
查看 Git 日志
如何修改 git commit 信息
vim
编辑器的使用
- 按下
i
键,进入插入模式,可以修改提交信息。- 按下
Esc
键,退出插入模式,回到命令模式。- 在命令模式下,输入
:wq
,保存并退出编辑界面。- 在命令模式下,输入
:q!
,放弃修改并退出编辑界面。
暂存工作区
多个上游的管理
需要多种命令的组合