# Gitlab Usage 这里简单写一下如何使用Gitlab [toc] ## Git账户 在完成账户注册后,需要前往个人用户preference中添加自己的ssh密钥或者gpg密钥 简单来说,ssh密钥和机器绑定,gpg可以携带使用 ### ssh key ssh密钥生成这里不细讲了,如果机器本身曾配置过ssh远程登录,可以直接复制个人用户目录下.ssh/id_rsa.pub中的publickey到文本框中 ![sshkey](doc/gitlab-sshkey.png) 通过 ``` ssh -T git@git.lejurobot.com -p 11026 ``` 可以查看是否可以通过验证 使用ssh公钥认证请在clone的时候选择ssh协议,或自己修改为ssh地址,否则可能在push时走https协议需要其他验证。 ### gpg key gpg是github比较通用的一种加密方式,可以携带在github上使用,也可以携带在gitlab上使用,只要有gpg密钥,就可以使用gpg加密,目前github已经取消了用户账户密码登录的方式,因此这里建议使用gpg密钥。 gpg密钥生成和ssh的基本一样,完成添加gpg密钥后,在进行git操作时,当需要填写用户名和密码时,使用gpg密钥替换密码即可。 ### 密码 gitlab貌似仍然可以使用用户密码来进行验证,但是这里不推荐,相对来说不是很安全。 PS: 当前gitea使用密码登录,安全起见关闭了ssh,只支持https的clone和提交 ## Git仓库建立 这里比较简单,在网页中选择Create blank project即可,在其中键入项目名就基本完成了,根据需要选择是否公开仓库。README可以在这里初始化,也可以自己创建仓库后在本地添加README。 ![blank-project](doc/gitlab-blank-project.png) ## Git命令 因为Git的命令往往需要联动来使用,这里通过例子来讲解用法 ### 1. 克隆仓库 ``` git clone https://git.lejurobot.com/luo980/gitlab-usage git clone ssh://git@git.lejurobot.com:10026/luo980/gitlab-usage.git ``` 这里需要注意的是克隆的地址中包含具体协议,可以通过 ``` git remote -v ``` 来查看当前仓库的地址。 PS: 如果第一次安装git,需要设置账户名和邮箱名 ``` git config --global user.name 'xxxx' git config --global user.email xxxx@yyyy.com ``` #### ssh ![ssh](./doc/gitlab-clone-ssh.png) #### https ![https](./doc/gitlab-clone-https.png) ### 2. 提交文件 提交文件使用git add来添加文件,通常直接使用“.”来自动添加当前路径下的所有文件,如果需要添加指定文件,可以指定路径和文件名。完成git add后就可以提交commit ``` git add . git commit ``` 进行commit时可以看到具体commit信息,在第一行中填写commit信息,如果不填写,则会因为提交说明为空而终止提交。 PS:以上命令建议新手熟悉过程使用,对于经验丰富的人可以直接使用git commit -am “commit message”,直接省去add和commit的步骤。 ### 3. 推送到远程仓库 完成提交commit后,可以使用git push来推送到远程仓库,这里需要注意的是,如果没有指定远程仓库,则会推送到默认的远程仓库,如果没有默认的远程仓库,则会提示错误。 ``` git push ``` PS: 在push的时候就会进行用户验证,注意至少使用一种验证方法。 在完成以上几步之后就可以实现提交本地仓库更改到远程了,如果需要推送到其他仓库,可以使用git push -u origin master来推送到指定的仓库。 ### 4. 拉取远程仓库 拉取远程仓库适用于多人协作或者多端多地协作的场景,当某个设备提交了更新的commit到远程后,本地的仓库就会落后于远程的仓库,这时为了获取最新的commit,可以使用git pull来拉取远程仓库的更新。 ``` git pull ``` eg:在实验室提交的更改,回到宿舍pull下来继续加班,然后在宿舍加班push,回到实验室再pull下来... eg: A写的bug提交后push到服务器,让B来pull下来修,B再push给服务器后,A再pull下来bug继续debug... ### 5. 其他常用git命令 ![git-command](./doc/git-commands.png) 这里以PlayGround项目为例,介绍图中菜单中的常见命令 #### 5.1 Commit Hash & Commit Subject Commit Hash就是每个Commit的唯一标识,通常是一个40位的字符串,每次提交都会生成一个新的Commit Hash,通过git log可以查看Commit Hash,使用git checkout可以切换到指定的Commit Hash。 ``` commit 38a0e56049b3043ae0d10f85354a3f5856466440 (HEAD, origin/main, origin/HEAD, main) Author: Gitea Date: Fri May 27 16:11:26 2022 +0800 what not committed commit e96cd67604df15dc04b90890edfbde73539a4871 Author: Gitea Date: Fri May 27 16:10:53 2022 +0800 third commit a5b56555531096716271405b44870167d81315ae Author: Gitea Date: Fri May 27 16:09:48 2022 +0800 second commit 22cd0a246211e9e8e9f636afe3c843023d6a998a Author: Gitea Date: Fri May 27 16:03:33 2022 +0800 First commit d679c806b7a807065d7637db6388705a849968d1 Author: Gitea Date: Fri May 27 15:15:13 2022 +0800 "first" commit a80d56007cdc5d88f0d3e997e8803b7c0a94c7bc Author: 罗朝欣 ``` 这里展示的就是Playground的提交记录,每个Commit的Hash和Commit的Subject,其中Commit的Subject是一个可以被git log查看的字符串,可以理解为提交的描述信息。 PS:后面Author是Gitea的原因是本地搭了一个Gitea服务器,没改回来git用户名称... #### 5.2 Tag Git的tag本义为标签,是一个特殊的Commit,它的Subject是一个标签,比如v1.0.0,一般用来记录版本信息。 ``` // 当前位置创建tag git tag // 删除名为的tag git tag -d // 给指定的Commit创建tag git tag ``` ![tag](./doc/tag.png) 这里示例添加了一个tag,在有了tag之后,使用checkout切换分支时即可以使用tag来切换到指定的Commit,比如checkout v1.0.0,则切换到v1.0.0的Commit。 #### 5.3 Branch Git的branch为分支,一般用于给程序添加feature功能时创建,在branch中完成开发后再完成后再合入master,与tag不同的是,branch具有一个head指针,指向Commit,而tag只有一个指向Commit的指针,不具有head指针。 ``` // 在当前位置创建一个新的分支 git branch // 删除分支名为的分支 git branch -D ``` 创建分之后同样可以通过checkout来进行切换。 PS: 这里可以看到,我在提交了新的commit后,branch依旧前进,但是tag停留在了上一个版本。 ![branch-tag](doc/branch-tag.png) PS: 这里会遇到当远程不存在本地的branch时,可以将本地的branch推送到远程的上游upstream,这样就可以在远程上游的branch中找到本地的branch了。 ``` git push --set-upstream origin ``` #### 5.4 Checkout 在介绍完tag和branch后,我们来介绍checkout,checkout是git的一个重要命令,它可以切换到指定的Commit、分支、tag。 ``` git checkout // ``` 使用checkout后,可以通过git log来查看当前的Commit,也可以通过git diff来查看当前Commit和上一个Commit之间的差异。 PS: 如果不想checkout到某个Commit来查看目标文件,可以使用git checkout (commit-hash) (file-name)来进行查看。 ![checkoutfile](doc/checkout-file.png) 如图是我在最新的Commit中修改了first文件,但是只想查看上个版本中first文件是什么样的,因此我使用了git checkout v3.0 first恢复了tag为v3.0时的first文件。 #### 5.5 Merge Git的merge是用来将两个分支branch合并在一起,合并后的分支branch叫做merged branch,合并前的分支branch叫做unmerged branch,这里就容易出现冲突的情况: ![err-merge](doc/err-merge.png) 遇到这种情况时,会在本地冲突文件中添加冲突说明, ![conflict](doc/conflict.png) 在手动解决后,删掉注释部分重新commit即可,如图即完成了merge操作,可以看到两个branch合并在了一起。 ![merged](doc/merged.png) #### 5.6 Revert Git的revert如其名就是用来回退到某个Commit,这里我们可以通过git revert (commit-hash)来回退到某个Commit,如果我们想回退到某个Commit之前的Commit,可以使用git revert (commit-hash)~1来完成。同样也可以用来回退文件,只需要在git revert (commit-hash) (file-name)来完成。 ![revert](doc/revert-forth.png) 这里我创建了forth文件并完成了commit,然后使用revert命令回退了这次commit,因此forth文件被删除。 #### 5.6 Cherry-pick Git的cherry-pick是用来选取某个Commit的差异,并将其作为新的Commit提交到当前分支中。 eg: 在master分支上提交了一个Commit,但是在develop分支上没有提交,这时我们可以通过cherry-pick将master分支上的Commit提交到develop分支中,这样develop分支就可以拥有master分支的Commit。 ``` git cherry-pick ``` #### 5.7 Rebase 这里不推荐使用rebase命令,rebase本义是改变基底,实际使用时是将本地的修改提交到另一个branch的最新Commit上,容易出现因为使用rebase而出现提交历史混乱的问题。 ref: https://zhuanlan.zhihu.com/p/387438871 #### 5.8 Reset Git的reset命令很好理解,它可以将本地的工作区域恢复到某个Commit、Tag、branch,同时配合--hard命令可以用来调整HEAD位置。 ``` // 将本地的工作区域恢复到某个Commit git reset // // 调整head git reset --hard ``` ## 开发者一般开发操作 ### 个人从零开发 个人从零开始开发一般不需要注意太多,那么自己作为Maintainer管理自己上传的代码即可,当创建branch后需要merge操作,需要在gitlab界面中create merge request来进行code review,最终完成合并。 ### 小团队开发 小团队开发时,一般需要指派一个管理者作为Maintainer,组员基于主线项目开发时,需要单独创建branch,并merge到主线上,这样就可以避免团队中的人在开发时出现冲突,最终完成合并。在进行合并操作时,需要Maintainer创建merge request,选择自己同意merge方案或者指派一个组员来进行code review,最终完成合并操作。 ### Tag 和 Branch Tag一般为了给可用版本的代码打下快照使用,Branch一般为了给开发者提供一个可以自由发布的版本,一般在开发时创建,在发布时删除。 ## tips 如果在提交时遇到多次请求用户名和密码的情况,可以考虑缓存凭证 ``` // default 15min git config --global credential.helper cache // cache for 3600s git config --global credential.helper 'cache --timeout=3600' ```