文章目录(Table of Contents)
简介
这一篇会介绍关于 Git
的相关操作。包括基础的 Git
的简单配置,SSH
的关联设置. 会介绍一次完整的 Git
的操作,包括 add
,commit
和 push
。同时,我们会介绍 Git
中的分支的内容。
参考链接
- Git 的下载, Git Download
- 实验楼中关于 git 的课程, 还是不错的(这个是免费课), Git 与 GitHub 入门实践
Git 的简单配置
Git 的本地配置
使用git config -l
来查看 git 的相关配置信息. 所有的这些配置信息, 都会存储在主目录的隐藏文件.gitconfig
中. 我们也可以对这个配置文件直接进行手动的修改。
设置全局的用户名和邮箱
我们可以通过下面的方式来配置全局的 username
和 email address
。
Set your username(设置全局的用户名):
- git config --global user.name "FIRST_NAME LAST_NAME"
Set your email address(设置全局的邮箱地址):
- git config --global user.email "MY_NAME@example.com"
对特定的仓库设置用户名和邮箱
除了对全局进行设置之外,还可以单独对某个仓库进行设置,首先进入对应文件夹:
Set your username(设置用户名):
- git config user.name "FIRST_NAME LAST_NAME"
Set your email address(设置邮箱地址):
- git config user.email "MY_NAME@example.com"
设置完毕之后,我们可以确认一下相关的 config
文件:
- cat .git/config
克隆仓库到本地
我们使用git clone + (仓库地址)
即可克隆仓库到本地. 下面是一个简单的例子. 后续会基于这个例子进行.
- git clone https://github.com/wmn7/ML_Practice.git
当我们克隆一个远程仓库到本地, 本地仓库会自动关联这个远程仓库. 使用git remote -v
可以查看本地仓库所关联的远程仓库的信息. 在github上, 主机名就是这个仓库地址.
添加 SSH 关联授权
为了避免每次输入账号密码的麻烦, 我们可以在系统中创建SSH公钥和私钥. 并将公钥放在Github(或是GitLab等其他托管的地方)指定位置, 这样既可以生成Git账户对于当前系统的Git授权.
首先我们在终端执行ssh-keygen
命令, 生成公私钥对. 公私钥对放在主目录的隐藏目录.ssh
下. 点击进去可以看到有两个文件, 如下所示:
我们将id_rsa.pub中的公钥内容复制出来, 在Github(或是GitLab等其他托管的地方)中添加公钥(一般的操作是Setting->SSH Keys->New SSH Key). 添加完毕之后, 我们可以进入我们要克隆的仓库, 找到SSH的链接, 接着使用git clone (SSH 链接)
即可.
通过 HTTPS 来使用 SSH 连接
如果希望使用 SSH 但无法通过端口 22 进行连接,则可以通过 HTTPS 端口使用 SSH。详细的说明可以参考这个链接,Using SSH over the HTTPS port。
首先我们先验证是否可行,按照下面的命令进行操作,查看是否得到一样的结果。
- $ ssh -T -p 443 git@ssh.github.com
- > Hi username! You've successfully authenticated, but GitHub does not
- > provide shell access.
要是可以,那么编辑配置文件 ~/.ssh/config
,写入以下内容即可:
- Host github.com
- Hostname ssh.github.com
- Port 443
- User git
关于上传新的仓库
我们可以现在 github 上新建一个仓库,再把本地的文件push上去。具体的方法如下所示:
- cd existing_folder
- git init
- git remote add origin url
- git add .
- git commit -m "Initial commit"
- git push -u origin master
Github 修改默认分支
如果我们在项目中包含多个分支,我们可以修改默认的分支。修改默认分支需要在 github 的页面设置中进行操作。
在「仓库的主界面」->「设置」->「Branches」->「Default Branch」中可以进行修改,具体的界面如下图所示:
关于更加详细的资料,可以参考下面的链接,Changing the default branch
Github 私有仓库添加成员
当我们在 Github
建了私有仓库,想要往里面添加成员,可以点击「Settings -> Manage access -> Add people」即可添加合作者,完整的如下图所示:
关于.gitignore的说明
在我们写代码的时候, 总会出现一些不需要上传到仓库的代码, 缓存文件等. 这个时候就可以创建一个.gitignore(忽略文件)将这些不需要上传的文件进行忽略. 忽略文件的名称是.gitignore, 他会被存放在仓库的主目录下. 关于一些常见的忽略文件, 可以查看链接, gitignore
我们也可以通过vscode的插件, gitignore来完成相关文件的生成.
安装完毕之后, 使用Ctrl+Shift+P打开命令, 搜索Add gitignore.
之后选择语言, 进行添加即可.
关于如何在设置了 gitignore
之后,还进行强制的 git add
,请参考后面 git add
的部分。
关于Watch, Star和Fork
首先我们介绍一下下面的三个标志.
- Watch, 点击Watch之后, 会对一个仓库进行关注, 仓库更新可以在首页得到消息.
- Star, 类似与收藏的功能, 觉得这个项目好, 就可以使用Star.
- Fork, 点击fork, 可以克隆一个完全一模一样的仓库到自己的账号上, 包括所有的分支和提交等. 但是当原来的仓库版本发生改变, 是不会自动同步到自己克隆的仓库中去的.
Git的基础操作
在这一部分, 我们会完成一次从本地仓库修改代码, 提交并推送到远程仓库的操作. Git的整体的操作流程如下图所示, 其中:
- Working Directory: 工作区
- Staging: 暂存区
- Local Repository: 本地的仓库, 版本区.
- Remote Repository: 远程仓库
查看仓库状态-git status
进入仓库目录, 使用git status
查看整个仓库的状态. 此时没有需要提交的文件.
此时我们对仓库里的文件进行一些小的修改, 这一步是在工作区中进行的. 修改完毕之后再次使用git status
进行查看状态.
可以看到有需要git add的内容.
添加修改到暂存区-git add
于是, 我们按照上面的提示, 使用git add (文件名)
把新增文件添加到暂存区. 接着我们再次使用git status来查看仓库状态.
如果有很多文件需要添加, 可以使用git add .
来全部添加到暂存区. 当有的文件是在 gitignore
中的时候,我们可以使用 -f
的方法来强制添加。
强制添加-git add -f
在 git 中,是有一个全局的 gitignore
的,其中就包含了 exe
文件是不会被上传的。但是如果我们就想要上传 exe 文件呢,此时可以使用 git add -f
来强制进行上传。
我们可以首先使用 git check-ignore -v 来查看以下我们的文件是否被 ignore,以及是哪里的规则导致其被忽略。
- git check-ignore -v -- yourFile
我们查看 exe
文件被 ignore
的原因,可以看到是因为 gitignore_global.txt 中的规则导致的。
为了可以将 exe
文件上传上去,可以使用下面的命令来进行上传。
- git add -f yourFile
关于这一部分的详细的内容,可以参考下面的链接,git does not recognize exe file
撤销暂存区的修改-git reset
如果我们有些修改添加错了, 需要撤销暂存区的修改, 可以使用git reset -- 文件名
, 或是git rm --cached 文件名
即可. 可以看到撤销之后所有内容又回到了工作区. 可以看到git status中会有提示需要进行git add.
如果需要撤销全部的修改, 可以使用git reset --
, 此时不需要后面的文件名.
比较修改内容-git diff
当我们想要查看文件修改的地方的时候, 可以使用git diff的命令.
git diff
, 可以查看工作区被跟踪的文件修改情况.git diff --cached
, 查看暂存区内修改的情况(也就是在git add .之后进行查看不同)
提交版本-git commit
接着我们执行git commit
将暂存区的修改提交到本地仓库, 版本区. 这个时候会生成一个新的版本. 我们需要使用选项-m来提供相应的备注. 例如, git commit -m 'generate mosaic image'
提交后, 暂存区的修改被清空. 关于提交 commit,在 VS Code 中会有一些模板可以使用,具体插件的使用见下面的链接,VS Code 插件--git commit 模板生成
查看分支信息-git branch
在提交之后, 我们可以来查看全部的分支信息, 使用git branch -avv
. 会得到如下的结果:
下面我们一一来解释一下:
- 第一行, 开头的星号表示所在的分支, 后面是版本号. 中括号内的内容, 表示此分支的远程分支的名字, 冒号后面的内容表示本地分支领先远程分支一个提交. 最后就是commit时的备注信息.
- 第二行, 是git的信息指针, 指向远程的master分支.
- 第三行, 是远程分支的信息.
查看提交的历史-git log
我们可以使用git log
来查看版本区的提交历史. 有以下的一些常见的用法.
- git log 分支名, 查看某个分支的提交历史, 不写分支名查看当前所在的分支.
- git log --oneline, 一行显示提交历史.
- git log -n, 查看最近n次的提交.
- git log --author 贡献者名字, 查看指定贡献者的提交记录.
- git log --graph, 提示法显示提交历史.
我们看一下git log --graph最后的效果, 前面的十六进制就是提交的版本号, 每个提交都有自己独特的版本号.
将本地仓库提交到远程-git push
最后一个环节, 是将本地新增的提交推送到远程仓库中. 他的命令是git push
. 此命令会把本地仓库master分支上的新提交推送到远程仓库同名的分支上. 因为现在本地所在的分支就是master, 远程也是, 所以直接更新远程的仓库.
这里在使用git push的时候, 会要求输入账号和密码, 按要求进行输入即可.
当push成功之后, 我们再使用git branch -avv
来查看, 可以看到此时本地分支和远程分支的版本号是一样的.
版本回退-git reset
如果发现我们提交的内容有问题, 我们可以选择重新走一遍上面的流程, 及修改, git add, git commit, git push. 我们也可以撤销最近的一次提交.
我们使用git reset --soft HEAD^
来撤销最近的一次提交, 将修改返回到暂存区. 其中HEAD^
表示撤销一次提交, HEAD^^
表示撤销两次提交.
但是一旦本地的版本回退之后, 本地仓库和远程仓库会在提交版本上有冲突. 这是因为撤回是在本地撤回的, 这个时候再需要将本地的推送到远程, 需要增加一个参数, -f, 表示force, 即强制推送. git push -f
.
回退到某个版本-git reflog
在本地仓库中, 会记录每一次提交的版本. 这个只记录在本地的仓库中, 一旦本地仓库删除, 记录就会消失. 我们可以使用git reflog来查看提交的历史.
可以看到这里记录了两次操作, 分别是git clone和git commit的操作.
如果想要回退到某个版本, 我们可以根据上面每一行HEAD的信息, 使用git reset --hard HEAD@{0}
来退回到指定的版本.
Git的分支管理
刷新分支目录
有的时候我们需要看一下远程哪些分支被merge了, 现在还有哪些新的, 可以使用下面的命令.
- git remote update origin --prune
刷新本地的分支信息-git fetch
有的时候, 我们需要把远程仓库的分支信息拉取到本地仓库中, 这个时候需要使用git fetch
. 该命令只是刷新保存在本地的远程仓库的信息. 可以使用 git fetch origin
。
例如现在远程的仓库有了更新, 本地还没有更新. 我们使用git fetch更新一下. 可以看到先在本地的分支落后远程的分支一个版本.
更新本地分支内容-git pull
上面的git fetch只是刷新在本地的远程分支的信息. 如果想要使得本地的分支是最新的, 就需要使用git pull
命令来拉去远程分支到本地.
如果上面使用了git fetch, 也可以直接使用git rebase origin/master
来实现本地的分支的更新. 下面我们使用git rebase来进行本地仓库的更新, 可以看到跟新后本地和远程的版本号就是一样的了.
创建和切换新的本地分支-git branch/git checkout
分支在多人开发中有着很大的作用. 例如现在有一个项目, 需要有两个版本进行测试, 测试的内容显然不可以直接在正式的分支上进行修改. 所以我们需要创建新的分支来存放不同版本的代码. 一般情况下, 不同的团队成员都在自己的分支上进行修改, 然后向 master 提交 PR(pull request).
首先我们在主目录下可以查看分支的信息, 使用git branch
来查看分支信息.
接着执行git branch 分支名
可以创新新的分支. 可以看到下面创建完成之后, 再次查看可以看到我们刚刚创建的分支.
接着我们使用git checkout 分支名
来进行分支的切换. 可以看到现在我们成功切换到了 dev 这个分支上面. 需要注意的, 新建分支没有跟踪任何远程的分支, 所以不像master分支那样会有蓝色的远程分支的名字.
我们也可以使用git checkout -b 分支名
, 来创建分支并切换到新的分支.
提交新的分支-git push
现在我们在新的分支上修改内容, 再次使用git status
来进行查看. 可以看到是在dev分支上. 我们对修改的内容进行提交.
现在我们需要把我们新的分支提交到版本区, 我们使用git push 主机名 本地分支名:远程分支名
, 如果远程分支不存在, 就会自动进行创建。如果本地分支名和远程分支名是一样的,就可以进行省略。可以写成下面的形式, git push 主机名 本地分支名
(这里「主机名」一般都是 origin
,Git 里面的 origin 到底代表啥意思?)
下面我们首先来提交一下这个分支:
我们提交一下我们这个分支,接着来查看一下。可以看到此时远程分支的信息已经存在了:
这个时候再看GitHub的页面, 就可以看到一个多的的分支的选择了.
新的分支与远程分支关联
上面我们在查看分支信息的时候, 可以看到新的分支并没有和远程的分支关联. 即没有中括号里面蓝色的内容. 我们可以使用git branch -u [主机名/远程分支名] [本地分支名]
来将本地分支与远程分支进行关联. 可以看到下面就是成功关联了.
同样, 我们也可以在push的时候就自动追踪远程的分支. 使用git push -u 主机名 本地分支名:远程分支名
.
删除远程分支
我们可以使用git push 主机名 :远程分支名
来进行删除, 这个命令是将空分支推送到远程, 这样也就把分支删除了.
另一个删除远程分支的命令是, git push 主机名 --delete 远程分支名
, 来进行删除.
此时只是删除了远程的分支, 本地分支还没有被删除.
本地分支的更名与删除
上面我们删除了远程分支, 这里我们将本地的分支也删除. 需要注意的是, 不能删除所在的分支, 所以我们需要先使用git checkout来进行分支的切换, 再进行删除. 我们使用git branch -D 分支名
来进行本地的分支的删除.
多人协作的 Git 部分
下面介绍一下完整的多人合作的时候应该如何来做。下面要讲的是使用 fork
的方法。当然我们也可以不 fork,直接克隆主仓库,然后创建自己的分支,在自己的分支上进行修改和提交。最后从自己的分支向 master 进行PR。但是这里讲一下 fork
相关的内容。
克隆仓库到本地并进行修改
- 首先我们需要
fork
一个官方的仓库; - 接着我们以成员的身份将其克隆到自己的本地;
- 之后我们就在我们克隆的仓库中进行修改;
提 PR 和检查合并 PR
在我们完成修改之后,应该如何将新的仓库提交到组长的仓库呢。这里就需要使用 pull request
方法。 我们稍微介绍一下 PR 的过程。创建一个 PR 就是从甲分支向乙分支提一个请求,这个请求中有一个或者多个提交。要是乙觉得没有问题,就可以进行合并(merge)。这个整个过程就是 PR。
同步主仓库
作为组员,我们需要保证自己的 master
分支和组长是一样的,这样可以避免在 PR 的时候出现问题。 那么我们首先使用git remote
来增加一个关联主机。完整的命令是, git remote add 主机名 主仓库地址
. 一般主机名使用 up,只需要不是 origin 重复即可.
在增加之后我们再次查看,可以看到此时就会多出两个地址:
之后我们就使用之前学过的 fetch 来拉取远程仓库的信息. git fetch 主机名
. 如果在 git fetch 的时候出现报错, fatal: Authentication failed for, 很可能是我们账号密码输错了. 在Windows中, 可以在设置中搜索凭据管理, 把密码删掉后重新进行输入即可.
在拉取信息之后, 我们需要同步主仓库. 有下面两种方法:
- git pull --rebase up master, 这一种方法是包含git fetch的
- git rebase up/master
所以, 相当于是git pull --rebase up master = git fetch + git rebase up/master
. 在完成主仓库的同步之后, 可以继续修改自己的master分支, 最后一起提交到远程仓库.
解决冲突
当我们使用命令 git merge test
之后,如果告诉你出现冲突,我们就要手动进行解决。当有了冲突之后,我们可以使用 git status 来查看冲突的内容,并解决冲突:
当解决了冲突之后,我们使用 git add 重新进行提交即可。
Git 标签
在一个项目中,我们可能需要阶段性地发布一个版本,比如 V1.0
、V1.0.2
、V3.2 Beta
之类的,Git 的标签可以满足这个需求。在一个长期大型项目中,可能会有数千个提交版本,我们可能需要对重要的节点性提交打个记号,这时也可以使用 Git 的标签功能。
重要的一点,我们创建标签是给具体的某次提交创建的,跟分支无关。创建标签使用 git tag [标签名] -m [备注信息] [提交版本号]
这个命令。其中 -m [备注信息]
可以省略不写,但建议不要省略。[提交版本号]
可以省略,如果是给当前分支最新的提交创建标签的话。具体可以使用下面的命令来创建一个标签。
- git tag v0.1 -m 'xxxxxxxx'
执行 git tag
命令显示仓库中的全部标签列表,执行 git show [标签名]
查看标签详情。
推送 tag 标签
我们可以执行 git push origin [标签名]
推送标签到远程仓库。如果有多个 tags,可以使用 git push origin --tags
命令将全部本地标签推送至远程仓库。例如上面我们新建的 v0.1 这个版本,可以使用下面的命令进行推送:
- git push origin v0.1
删除本地 tag 标签
当我们执行 git tag [标签名]
创建本地标签后,在仓库主目录的 .git/refs/tags
目录下就会生成一个标签文件。执行 git tag -d [标签名]
删除本地标签,标签文件也会被删除。
删除远程 tag 标签
如果标签废弃不用或者写错了,可以使用 git push origin :refs/tags/[标签名]
删除远程仓库的标签,命令中的标签名其实也就是文件名。
远程删除成功之后,我们需要手动删除本地的 tag。删除的方法如上所示。
签出版本
假如说我们现在需要基于一个 tag 继续做开发,我们可以首先切换到这个版本,然后再在当前的版本上新建一个分支即可。假设我们现在要签出 001 版本,执行以下步骤即可。
- 首先执行
git checkout [标签名]
切换到之前的某个提交版本; - 然后执行
git checkout -b [新的分支名]
将此提交版本固定到一个新分支上并切换到此分支
Git 的一些问题
出现错误-fatal: The remote end hung up unexpectedly
这个可能是由于推送的文件太大,我们可以通过修改 config
文件来解决问题。
- 打开仓库所在目录,显示隐藏文件可见;
- 打开并编辑
config
文件,在最后加上下面的内容即可;
- [http]
- postBuffer = 524288000
参考链接, Git:解决报错:fatal: The remote end hung up unexpectedly
Git 里面的 origin 到底代表啥意思?
首先我们看一下 origin 是从哪里来的。在我们新建新的仓库的似乎后,通常会使用下面的命令:
- git remote add origin git@github.com:imki911/myProject.git
origin
就是在这里出现的,可以将 origin
看成是 code>git@github.com:imki911/myProject.git 的别名。所以我们可以将上面 origin
改成别的名称。
当一个用户(user2
) fork
了一个仓库并进行 clone
的时候,如果他输入 git remote -v
,那么他会在控制台看到如下的输出,可以看的 origin
指向的位置是 user2
的的远程代码库:
- origin https://github.com/user2/repository.git (fetch)
- origin https://github.com/user2/repository.git (push)
如果此时用户想要添加一个远程连接,指向原始的代码仓库(这样可以方便与原始的仓库进行同步),那么可以使用 git remote add
进行添加,下面的 upstream
就是一个别名:
- git remote add upstream https://github.com/user1/repository.git
这个时候再输入 git remote -v
,会看到如下的结果,upstream
指向了 user1
的仓库链接,origin
指向了 user2
的仓库链接:
- origin https://github.com/user2/repository.git (fetch)
- origin https://github.com/user2/repository.git (push)
- upstream https://github.com/user1/repository.git (push)
- upstream https://github.com/user1/repository.git (push)
所以总结一下,origin
指向的是 repository
,可以认为是一个 repository
的别称。
- 微信公众号
- 关注微信公众号
- QQ群
- 我们的QQ群号
评论