Git学习笔记:基础使用与搭配Github的使用
本随笔用于记录随笔作者在一般情况下使用Git的一些步骤和操作,主要用于在经过一段时间没有使用Git后能够通过该随笔马上回忆起基础操作,所以该随笔一开始并不会介绍Git的高级特性。本随笔内容摘录自官方教程
随笔作者还在学习当中,难免会出现书写上和技术上的错误,如果发现类似错误,欢迎在评论区或私信与我讨论。
该随笔将会不定期更新。
特别提醒:因为该随笔主要是记录操作,而不涉及Git的运行原理,因此关于工作目录、暂存区域、仓库等概念恕不赘述,可以查阅官方的文档了解。
Git的配置
当安装好git之后第一步就是对Git进行配置,主要就是设置用户名和邮箱,方便和其他人协作。
配置用户名和邮箱
git config user.name <UserName>
git config user.email <UserEmail>
第一条命令用于设置用户名,第二条命令用于设置邮箱。用户名和邮箱会被记录在你的每次Git提交上。例如我要设置我的用户名则我会输入如下命令:
git config user.name U.N.Owen
如果你发现没起作用并报错,而且也确实应该没有作用,不用担心,请参阅默认的配置文件存储位置小节。
配置文本编辑器
git config core.editor <EditorName>
在使用Git的过程中会频繁的使用到编辑器(例如提交时编写提交信息),所以指定一个自己常用的编辑器可以提高开发的效率。例如我要指定Vim作为Git的文本编辑器则我需要输入如下命令:
git config core.editor vim
配置文件的存储位置
Git在配置上述字段的时候允许用户传递参数来选择位置用于存储配置文件:
--system
:选择系统位置来存储配置文件(在MSYS2环境下即保存到/etc/gitconfig
文件里),保存在这里的配置文件可以作用于该系统上全部用户的全部仓库。
--global
:选择用户位置来存储配置文件(在MSYS2环境下即保存到~/.gitconfig
文件里),保存在这里的配置文件可以用作于该系统上该用户的全部仓库。
--local
:选择当前的Git仓库来存储配置文件(即.git/config
文件里),保存在这里的配置文件仅仅可作用于该仓库,这也要求我们的shell工作目录是在Git的一个仓库目录里。
例如,我想添加一个用户名到系统上,这样以后我在使用其他Git仓库时就不再需要重复输入用户名,我可以使用如下命令来生成配置文件:
git config --system user.name U.N.Owen
默认的配置文件存储位置
当我们没有显示指定配置文件的存储位置时,Git会默认使用--local
作为存储位置,因此其隐式说明了我们首先必须有一个Git仓库才能配置文件,关于如何生成一个Git仓库可以参阅下面的初始化仓库小节。
Git的基础使用
初始化仓库
我们可以把任意一个目录当作我们的Git仓库目录,我们只需要在Shell里导航进指定的目录,然后运行以下命令即可让当前目录变成一个Git仓库:
git init
添加文件进行追踪
git add <filename or part of the filename>
该命令会将指定或符合的文件添加到仓库的暂存区域。
提交文件
git commit
该命令会将全部暂存区域内的文件提交到仓库里,并且打开编辑器要求用户编写提交信息,如果用户没有编写提交信息还会触发Abort从而导致提交失败,因为良好的编写提交信息习惯有助于我们以后查看自己的提交做了哪些事情。
如果我们不想每次提交都要打开编辑器编写提交信息,而只需要编写简短的内容,则可以使用如下命令在提交的同时附加上提交信息:
git commit -m <commit message>
有时候我们想提交已追踪但是又修改了的文件,同时我们也不想用git add
命令去添加到暂存区,那我们可以使用如下命令直接一次性把所有修改过的文件全部提交:
git commit -a
撤销提交
有的时候我们在提交之后会发现某些文件没有上传或者说提交信息写错了,这个时候我们又不想直接新建一个提交的时候,我们可以使用--amend
选项来执行“重新提交”操作:
git commit --amend
这个提交会“覆盖”掉上一个提交,让上一个提交像在提交历史中从来没有出现过一样(但实际上只是没有显示出来,在Git仓库里还是存在着对应的记录的)。
移除文件
git rm <filename or part of the filename>
该命令可以移除工作目录中的文件并对文件标记“已删除(Deleted)”状态(即rm了文件然后又git add了删除状态到暂存区),但是对于已添加进暂存区域或者在工作目录有修改的文件来说,执行该命令会失败并有错误提示。
git rm --cached <filename of part of the filename>
该命令可以移除暂存区的文件,但是不会在工作目录中对其删除。
git rm -f <filename>
可以忽视限制,强制从暂存区和工作目录里面删除指定的文件并暂存起“已删除”状态。
恢复文件
git restore <filename>
将工作目录的文件恢复为暂存区的文件,如果暂存区没有文件,则恢复到HEAD指定的文件。
git restore --staged <filename>
将暂存区的文件恢复到HEAD指定的文件。
详细的重置命令使用方法
Git对于重置命令有着一套比较复杂但完整的逻辑,可以参阅随笔作者写的另一篇文章命令reset和checkout在“重置”功能中的区别及其注意事项了解更详细地使用方法,其中也包括如何从历史记录里恢复某个被删除的文件的方法。
查看工作目录状态
git status
该命令可以打印出当前工作目录的状态,包括有哪些文件还没有被索引、哪些文件已经被索引还没提交、哪些文件已经索引但又被修改等等。
设置忽略列表
当我们在编译程序的时候经常会生成一些额外的文件,这些文件不需要我们跟踪到仓库里但是会经常出现在我们的git status
列表里,所以这个时候我们可以设置一个忽略列表让列表里指定的文件不受Git的监控和管理。
我们只需要在仓库的目录下创建一个名为.gitignore
的文件,然后在里面填写需要忽略的文件名即可,可以使用glob模式的正则表达式来指定文件名。
例如我要在一个UE4项目中使用忽略列表,则我的忽略列表文件内容应该如下显示:
.vs
Binaries
DerivedDataCache
Intermediate
Saved
*.sln
查看文件的修改
git diff <filename>
该命令可以查看暂存区和工作目录之间的文件(如果没有输入<filename>
则是全部文件)之间的差异。
git diff --cached <filename>
该命令查看的则是已提交和暂存区之间的文件差异。
查看提交历史
git log
该命令可以查看简略的历史提交记录。
git log -p
该命令可以在输出历史提交记录的基础上显示变更的内容,该命令非常适合于进行代码审查以及其他人的提交带来的变化。可以添加诸如-2
的参数来限制只显示最近的2
次提交。
为提交打上标签
轻量标签
git tag <tag> [<commit>]
该命令可以在当前提交上打上一个轻量标签,如果提供了[<commit>]
参数则可以在指定的提交历史上打标签。
附注标签
git tag -a [-m <tag message>] <tag> [<commit>]
该命令可以在当前提交或<commit>
指定的提交上打上附注标签,同时可以附加上-m <tag message>
作为标签的附注,如果没有附加上-m
参数的话则Git会打开编辑器让你编写附注。
删除标签
git tad -d <tag>
该命令可以删除本地仓库上已经建立的标签。
Git的远程仓库使用
克隆远程仓库
如果我们需要获取一个新的远程仓库,并将其建立在自己的磁盘上,可以使用如下命令去克隆一个Git远程仓库:
git clone <URL>
这样Git会在当前的工作目录上直接生成一个本地仓库文件夹,并在文件夹内将其远程仓库的内容拉取到本地仓库上。
查看远程仓库
在一个项目中很可能会使用到多个远程仓库,使用如下命令可以查阅当前我们的Git仓库记录了哪些远程仓库:
git remote
添加远程仓库
如果我们只是想添加一个远程仓库引用到我们的本地仓库,但是还不想将远程仓库的内容拉取到本地仓库里,更不想将起从本地仓库更新到工作目录里,可以用如下命令为我们的仓库添加远程仓库引用:
git remote add <shortname> <URL>
从已经添加了的远程仓库抓取内容
如果我们只想把远程仓库的内容更新到本地仓库,但是还不想从本地仓库更新到工作目录里,可以使用如下命令:
git fetch <remote name>
该命令从远程仓库拉取内容到本地仓库之后,同时还会更新远程分支的指向。
拉取远程分支上本地分支还未拉取的提交
git fetch <remote> <BranchName>
该命令可以获取远程仓库<remote>
的分支<BranchName>
的最新提交,并且把最新的全部提交拉取到本地分支<BranchName>
上。
拉取远程分支上不同名的本地分支还会拉取的提交
git fetch <remote> <source>:<desitnation>
该命令和上一个命令很像,但是最后一个参数分成了两部分:“源(Source)”和“目标(Destination)”,其中<source>
指定了远程分支的名称,而<destination>
指定了本地分支的名称。特别的,如果<destination>
分支不存在于本地仓库的话,Git会自动创建分支。该命令和git push
版本的命令很像,但是命令有点区别,需要注意。
从远程仓库抓取内容并更新到工作目录
如果我们已经设置了跟踪远程分支,则可以通过以下命令让我们在从远程仓库抓取内容的时候将当前分支合并到远程分支:
git pull
这也说明如果我们没有设置跟踪远程分支的话,要想将远程仓库的内容更新到工作目录上,我们只能手动合并分支来实现。
推送内容到远程仓库
当我们想要分享我们的内容时候,我们只需要将本地仓库的内容推送到远程仓库上即可,使用如下命令即可实现:
git push <remote> <branch>
和一般的版本控制系统的使用逻辑一样,如果我们拥有写入权限,同时之前没有人推送过的话,我们的推送才会成功,如果在我们之前有人已经推送过内容的话则我们的推送会失败,必须先把对方的内容工作内容合并到我们的工作内容,提交到仓库里之后才能推送成功,因为推送内容推送的是仓库里记录的内容。
推送本地分支还未推送的提交到远程分支上
git push <remote> <BranchName>
该命令可以通知远程<remote>
的分支<BranchName>
获取本地分支<BranchName>
还没有推送的提交,全部推送到远程仓库去。简单来说就是把指定的本地分支还没有推送的提交推送到远程分支上。
推送本地分支还未推送的提交到不同名的远程分支上
git push <remote> <source>:<destination>
该命令相比上一个命令很像,但是最后一个参数分成了两部分:“源(Source)”和“目标(Destination)”,其中<source>
指定了我们本地分支的名称,而<destination>
指定了远程分支的名称。特别的,如果<destination>
分支不存在于远程仓库的话,Git会自动创建分支。该命令和git fetch
版本的命令很像,但是命令有点区别,需要注意。
推送标签到远程仓库
无论是轻量标签还是附注标签,都不会保存到远程仓库上,如果要想把标签推送到服务器的话可以输入如下命令:
git push <remote> <tag>
或者你想一次性推送全部标签的话可以用如下命令:
git push <remote> --tags
删除远程仓库的标签
git push <remote> --delete <tag>
该命令可以删除远程仓库上指定的标签。
删除远程仓库
git remote remove
使用该命令会将所有和这个远程仓库相关的远程跟踪分支及配置信息一并删除。
Git的分支
创建分支
git branch <BranchName>
该命令可以在当前提交上创建一个新的分支。
切换分支
git switch <BranchName>
或git checkout <BranchName>
你可以使用checkout
或switch
命令来切换当前分支,这两个命令是等价的,只是switch
命令是新出(比起checkout
)的命令,而且该命令仅专注于分支操作,因此如果我们只需要切换分支的话最好使用switch
命令。
新建并切换分支
git switch -c <BranchName> <remote>/<BranchName>
或git checkout -b <BranchName> <remote>/<BranchName>
该命令可以为我们创建新分支的同时,将当前的HEAD
指针指向新的分支。如果我们指定了<remote>/<BranchName>
,则可以在新建并切换分支的时候设置追踪的远程分支。
合并分支
git merge <BranchName>
合并当前分支和指定分支<BranchName>
。
删除分支
git branch -d <BranchName>
该命令可以删除一个指定的分支。
删除远程分支
git push <repo> --delete <BranchName>
该命令会从远程仓库上删除指定的分支。
追踪远程仓库分支
上文我们讲到如果我们只是通过添加的方式(而不是通过clone
的方式)添加了远程仓库,那么我们当前的分支并不会自动追踪远程分支,也就不能进行pull
操作,所以我们已通过如下命令来让当前分支追踪指定的远程分支:
git branch -u <remote>/<BranchName> <BranchName>
我们可以指定<BranchName>
,来让我们需要的本地分支跟踪远程分支,如果不指定该参数的话则以当前HEAD
所在分支为本地分支。
查看追踪的远程分支
git branch -vv
该命令可以输出项目中所有分支及其追踪的分支(如果有),还可以看到我们当前的分支相较于远程分支的进度:“领先(Ahead)”代表我们本地有多少次提交还没有提交到远程仓库上;“落后(Behind)”代表远程仓库还有多少次提交没有合并入本地。
移动分支到指定提交
git branch -f <BranchName> <commit>
该命令可以让分支<BranchName>
的指针指向<commit>
提交,就像是直接移动了分支一样。
Git的储藏清理
Git能够很好的管理仓库里面的内容,但是对于工作目录和暂存区的内容Git很难追踪到,因此Git提供了“贮藏(stash)”功能,可以让我们暂时将工作区和暂存区的改动贮藏起来,然后在后续复原。这个特性很好的帮助我们在已经进行到一半的工作时我们需要切换分支,但是因为工作区未保存的内容导致切换失败,然后我们又不想强制切换分支导致工作进度丢失,这个时候贮藏就是一个很好用的工具。
贮藏内容
git stash
该命令可以将当前项目工作区和暂存区的内容全部保存到贮藏栈里面,并保持工作区暂存区没有任何修改。
查看贮藏的内容
git stash list
该命令能够列出来贮藏栈的内容。
恢复贮藏栈的内容
git stash apply [stash@{n}]
该命令能够从贮藏栈恢复工作进度到工作局和暂存区,如果指定了stash@{n}
参数的话则恢复指定的内容。其中n
是在git stash list
列表中显示的值(也可以说是索引)。
删除贮藏栈的内容
git stash drop stash@{n}
该命令会从贮藏栈里删除对应指定的贮藏。
恢复并删除贮藏
git stash pop [stash@{n}]
该命令实际上就是执行了apply
之后又执行了drop
。
与Github的搭配使用
Git和Github搭配使用最常见的场景就是Git从Github上面clone仓库,进行本地需改之后又推送到仓库上面去。但是基于Github的安全管理,我们需要一些安全措施才能正确克隆以及推送仓库,详细的Github安全管理措施可以查阅官方文档:管理个人访问令牌,文档里罗列了几种不同方式访问仓库时使用的安全措施,本随笔主要以HTTPS协议为主。
生成个人访问令牌
参阅Github的官方文档
需要注意的是,我们在生成个人访问令牌的时候需要把“仓库权限(Repository Permissions)”里面的“内容(Contents)”设置为“可读写(Read and Write)”,这样我们在使用Git的时候才能执行推送(push)操作。
如果我们在生成个人访问令牌的时候没有找到“仓库权限(Repository Permissions)”,只需要把“仓库访问(Repository access)”设置为“Public Repositories (read-only) ”以外的选项即可。
设置个人访问令牌
在我们的所使用的终端的用户目录里新建一个文本文件:.git-credentails
,例如我使用的是是MSYS2的Mintty,则需要把该文件生成在下列位置:
~/.git-credentials
然后在该文件里面输入我们要使用的个人访问令牌,其格式为:
https://<Username>:<PersonalAccessTokens>@<GitHost>
例如我的用户名为“UNOwen”、个人访问令牌为“3a3b3c”,git仓库网址在“github”上的话,上述格式就可以更改为:
https://UNOwen:3a3b3c@github.com
需要注意的是其中<Username>
最好为Git配置里面的user.name
。(随笔作者注:经过测试发现<Username>
填什么好像都不影响Github的验证,或者说是我的测试有问题,希望能够有知道的同学讲解一下其中<Username>
的用法,不胜感激)
设置Git凭证存储方式
git config --local credential.helper store
Git提供不同的凭证存储方式,在这里我们使用可以永续存储的方式,该方式的好处就是只要凭证不失效的话,以后我们在克隆或推送的时候都不再需要手动输入了。