Git 的正确使用姿势与最佳实践
由于我们组的队员大多都是大一大二的学生,之前大家都没有真正的工程实践经验,都听过Git是一个公认的版本控制神器,但是没有深度的使用过。刚好这次做大项目,是一个很好的机会好好研究一下Git的正确使用姿势。这篇文章就整理和记录一下学习和使用Git的过程。
开发环境说明
我们准备在GitHub上面建一个代码仓库用来存放项目代码,开发环境就直接使用1024code的代码空间。
接下来我们会记录一下从一开始创建代码仓库、代码空间,到在1024code上面连接远程空间、每个人分别在自己的代码空间用自己的分支进行开发,到最后提交代码、创建Pull Request、合并代码的整个过程。
准备工作
创建GitHub仓库
通过github.com/new来创建一个代码仓库,填好基本信息之后,点击Create repository完成创建。
这里我们创建的仓库地址是
创建1024code代码空间
在1024code.com主页点击上面的工作台,然后新建。这里我们选择Go作为代码模板,空间叫做git_demo。空间地址:1024code.com/ide/hhn4izj
代码空间连接远程仓库
在左边侧边栏有一个git图标,里面有一些使用Git的基本说明。我们选择“连接远程仓库”。按照说明,我们先添加公钥到GitHub。
然后在代码空间的shell命令行里面配置SSH连接
~/app$ git remote add origin git@github.com:claw16/git_demo.git
没有出错的话默认不显示任何返回信息。
接着拉取远程仓库:
~/app$ git pull --rebase origin main
The authenticity of host 'github.com (20.205.243.166)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 618 bytes | 77.00 KiB/s, done.
From github.com:claw16/git_demo
* branch main -> FETCH_HEAD
* [new branch] main -> origin/main
Successfully rebased and updated refs/heads/master.
从上面的信息可以看到我们成功拉取了github.com:claw16/git_demo这个仓库的main分支。
开发流程
做了一些功课,我们大致了解了一下敏捷开发的工作流程。这里总结一个简化的版本:
-
分配任务,把每个任务写成一个
JIRA ticket,分配给对应的开发者。 -
开发者拿到任务后,根据这个任务,建立一个自己的开发分支(从主分支拉取),进行开发工作
-
开发完成后,将开发的代码推送到远程仓库
-
创建一个Pull Request,指定一位合作开发者来审核代码
- 如果审核测试的过程发现了问题,需要重新修改,然后重复3、4步
-
审核完成后合并代码到主分支
我们来模拟实践一下这个开发过程。
分配任务
假设我拿到这样一个任务:
编写README.MD
开发任务
我们先从主分支上新建一个新的分支,叫做edit_readme:
~/app$ git checkout -b edit_readme
Switched to a new branch 'edit_readme'
可以看到我们已经新建并且切换到了edit_readme分支上,现在就可以开始开发了。
我们先修改一下README.MD,在里面加一行: Edited this file at 16:31 on 20230823.
然后查看一下当前的文件变化:
~/app$ git status
On branch edit_readme
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
可以看到这里显示README.md被修改了。
然后我们添加这个修改的文件,然后commit:
~/app$ git add README.md
~/app$ git commit -m "1st commit"
[edit_readme 58a917a] 1st commit
1 file changed, 2 insertions(+)
一般来说,开发的过程肯定不止一个commit,这里分享一些commit的好习惯:
- 每一小步commit一下,例如完成了一个功能,修复了一个bug,等等。这样审核的人通过我们的commit message就可以了解每一步做了什么
- 不要半途commit,如果一个功能做到一半,这个时候commit是一个不太好的习惯。如果非要commit,那么下次回来继续完成后半部分的工作之后,可以用
git commit --amend命令将后面一般的改动加到上一次的commit中 - commit之前充分测试我们的改动,可以的话最好写点必要的单元测试
- 尽可能清楚详尽地把我们做的改动写进commit message里面
然后同样地,我们接下来又开发了两个小功能,每一个都对应了一个commit。
我们可以用 git log 命令查看我们的commit记录:
~/app$ git log
commit 06ec0e09b6a61f5a3fb36aec60e2052e43a6bde8 (HEAD -> edit_readme)
Author: for shell <fromShell@paas.com>
Date: Wed Aug 23 17:23:59 2023 +0800
fixed a bug
commit 39666635c64aa534c9d419a486a8af47ef8dd107
Author: for shell <fromShell@paas.com>
Date: Wed Aug 23 17:23:31 2023 +0800
developed a new feature
commit 58a917a79747cf6c9f058e9827428153aef3d4a1
Author: for shell <fromShell@paas.com>
Date: Wed Aug 23 17:15:56 2023 +0800
1st commit
commit e54434b69036d17daa663cb3548f60db51c337fa (master)
Author: root <root@manager>
Date: Wed Aug 23 15:31:47 2023 +0800
Initial commit
commit 211147aa340c72f780034e2cabe8022a4865d27e (origin/main)
Author: claw16 <52300404+claw16@users.noreply.github.com>
Date: Wed Aug 23 15:09:44 2023 +0800
可以看到在edit_readme分支上我们有3个commit。
提交以及创建PR(Pull Request)
假设我们现在完成了开发,我们就可以把我们的改动提交到远程仓库:
~/app$ git push origin edit_readme
Enumerating objects: 17, done.
Counting objects: 100% (17/17), done.
Delta compression using up to 16 threads
Compressing objects: 100% (14/14), done.
Writing objects: 100% (15/15), 1.38 KiB | 1.38 MiB/s, done.
Total 15 (delta 5), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (5/5), done.
remote:
remote: Create a pull request for 'edit_readme' on GitHub by visiting:
remote: https://github.com/claw16/git_demo/pull/new/edit_readme
remote:
To github.com:claw16/git_demo.git
* [new branch] edit_readme -> edit_readme
可以看到这里将我们的分支上传到了远程仓库,并且在远程仓库建立了一个同名分支。同时也自动生成了一个链接,用于让我们创建Pull Request。我们可以直接打开这个链接。
在打开的窗口中,我们填写好PR的标题,言简意赅的表述一下这个PR做了什么,指定审核人,最后创建PR。
注意:如果我们不是通过自动生成的链接来建立PR,或者说链接有什么问题,我们就需要手动创建。手动创建时,除了刚才说的几个步骤之外,我们还需要手动指定从哪个分支合并到那个分支。
合并代码
当审核人完成审核,没有问题了,就可以直接点击Merge pull request,这样我们的分支就合并到远程仓库的主分支里面了。
后续开发
到这里还没有完全结束。到这里位我们只是完成了远程仓库上的合并分支操作,我们还需要将这个修改同步到本地。
我们需要先切换回主分支,然后在主分支上拉取一下远程仓库的主分支:
~/app$ git checkout main
Branch 'main' set up to track remote branch 'main' from 'origin'.
Switched to a new branch 'main'
可以看到现在切换回本地主分支了,然后之前做的修改也对应的回到了最初的状态。这时我们拉取远程主分支。
~/app$ git pull origin main
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), 610 bytes | 203.00 KiB/s, done.
From github.com:claw16/git_demo
* branch main -> FETCH_HEAD
211147a..e1bf84d main -> origin/main
Updating 211147a..e1bf84d
Fast-forward
.1024 | 9 +++++++++
.gitignore | 6 ++++++
README.md | 6 ++++++
go.mod | 3 +++
main.go | 9 +++++++++
5 files changed, 33 insertions(+)
create mode 100644 .1024
create mode 100644 .gitignore
create mode 100644 go.mod
create mode 100644 main.go
可以看到远程主分支的内容现在同步到本地了。
后续的开发就可以从更新后的主分支开始。
总结
这篇文章记录了在一个开发过程中如果正确地使用Git来进行代码管理。这只是一个精简的流程,实际开发中会遇到很多不同的场景。比如:
- 将本地的几个commit合并成一个commit提交给远程,可以用
rebase功能 - 本地开发时不小心直接在主分支上操作了,可以用
git stash功能来把当前的修改暂时隐藏并且存到一个栈里面,再切换到正确的分支用git stash pop操作把暂存的修改应用到正确的分支。 - 发现之前开发的东西有问题,可以使用
git revert功能来回滚 - …
Git是一个强大的代码管理、版本控制的工具,学好Git可以帮助我们更好地编程。