Git 及工作流

日常开发中,Git 必不可少,之前的文章我有简单介绍过 Git,具体看这篇,今天我介绍下 Git 的日常用法。

首先先看下这张图,这张图基本包括了 Git 的一些日常用法,并详细介绍了下它的工作流程。

虽然现在也有很多优秀的图形界面的工具,但使用 Git,我还是建议大家尽可能的使用命令行,以下都是在命令行中完成。

为了更好的说明 Git 的使用,这里我们通过一个例子来说明这些操作。

我要和小金合作一个叫着 t1 的项目,那么我进行了如下操作

cd t1 // 进入该项目文件夹
git init // 初始化项目
git config user.name 'tc' // 设置我的名字
git config user.email 'your email address' // 设置我的 email 地址
git remote add origin https://url-address.com/projectname // 设置项目远程库的地址

这个时候我设置好了基本信息,在配置 user.name 和 user.email 的时候,可以加上全局变量 --global,但并不建议这么做,如果你加上了,想去掉的话,可以执行命令

git config --global -unset-all user.name // 这样的方式

或者编辑 gitconfig 文件,位置在 ~/.gitconfig

就这样我对项目做了一些开发,比如

vi README.md // 编辑文件

编辑好 README.md 这个文件后,我又做了如下的操作

git add . // 增加这次编辑到索引
git commit -m "编辑更新 README.md 文件" // 将本次编辑信息提交到本地库

这样我本地的一次开发提交就完成了,那么该怎么和小金合作呢?这时就需要我把本地的库的内容提交到远程库(Remote)中

git push origin master // 将本地库中 master(某一分支) 的内容提交到远程库中,如果远程没有这个分支,则会自动创建

很多时候我们都不会直接在主干 master 上进行开发,我们都会开自己分支进行开发,这样做的好处很多,最起码的是我们不会扰乱主干。

执行下面的命令

git branch 分支名 // 在当前分支基础上创建我的分支
git checkout 分支名 // 切换到该分支

上面的命令也可以用一个命令来执行

git checkout -b 分支名 <来源分支> // 不加后面来源分支就是在当前分支下创建新分支,加来源分支则是其字面意思

这样我们就可以在这个新分支下进行工作,而不会干扰乱主干,在这个新主干上我又做了一些编辑,然后重复之前的命令 git addgit commit,最后我提交到远程库,这时注意,我提交的应该是我的新分支,而非之前的 master,命令应该是 git push origin 新分支名。

有时候在多个分支之间切换,忘了上一个工作分支的名字,则可以通过 git checkout - 回到上一个分支。

为了更合理的开发,这里引入一个开发模型,即本地应该有一个分支作为自身主干,然后再根据功能或喜好建分支做开发。

比如我会根据功能创建分支,完成分支功能后合并到本地的主干,因 CodeReview 以及备份的需要,要把本地主干的内容提交到远程库,操作如下

git checkout dev-local // 切换到作为本地主干的分支,合作的人多,会根据每人的 ID 命名,比如我的命名就是 dev-tc
git branch bugfix // 根据功能创建分支,这次我要做的功能是修正 bug

然后开始开发工作,做的过程中重复上面的命令定期 add 和 commit,完成该项工作,测试没有问题后,合并到本地主干分支 dev-local,执行命令

git checkout dev-local // 回到本地主干分支
git merge bugfix // 将 bugfix 的内容合并到 dev-local

这样本地主干分支就是我所开发的最新版本了,我会每次将这个主干内容定期 push 到服务器上的远程库中,一般离开电脑如果超过一个时间,在离开前就必须提交一次,比如吃中饭前和晚上下班前必须提交,CodeReview 的人会查看这些内容。一个分支的工作做完了,我觉得这个分支将不再有作用,就删除这个分支。

git branch -d bugfix // 强制删除,用参数 -D

另外还有一些命令也会经常用到

git branch -r // 查看远程分支
git branch -a // 查看本地分支

小金登场

随着小金加入到了项目中,我们就开始用 Git 进行团队合作,小金在终端中输入了下面几个命令

git clone 远程库地址 <本地目录名> // 后面的本地目录名是可选项,用于变更文件夹名字

这时候小金就把代码库克隆到本地,并且给远程库自动命名为 origin,他可以通过 git remote 查看,如果后面加参数 -v 则可以清楚的查看远程库的地址,下面是几个常见命令

git remote rename origin <新名字>  // 改成新名字,在 clone 的时候也可以用 git clone -o newname url地址,变更名字
git remote rm url地址  // 删除远程库地址
git remote show <代码库名>  // 显示该远程代码库详情
git remote add <代码库名> url地址  // 添加远程库地址

有时候我们可能有备份或者其他需要会把代码存放在不同的地方,那么我们会放到多个远程库中,则可以多添加其他地址

git remote add all url地址一
git remote set-url --add all url地址二
git push all --all

这样我们在push的时候就能 push 到不同的地方,这是额外插入的内容,小金继续工作,因为他是协助帮我开发一部分内容,所以他就要基于我的分支,但刚才的 git clone 并没有 clone 出我的分支,那么他就要做下面的操作

git checkout -b dev-xiaojin origin/dev-tc

基于我的分支创建他的分支,并进入到该分支,小金又根据功能创建了分支,然后写了一些新码,测试通过,合并到 dev-xiaojin 这个分支,与此同时,我也在写代码,并且提交到了远程库 dev-tc 中,那么小金在提交代码前,他需要先把我的代码合并到他的代码中

git fetch <远程库名/远程分支名> // 不带后面的选项表示更新所有的分支,带选项表示更新指定的内容
git merge <远程库名/远程分支名> // 将更新的代码合并到当前的工作的分支中,也可以用 git rebase <远程库名/远程分支名> 命令。

这时候可能会出现代码冲突的问题,按照提示解决,可能会觉得这样操作太麻烦, git pull 就更加直接。git pull 的意思就是获取远程库的更新内容并且和本地分支合并。

git pull <远程库名> <远程分支名>:<指定分支名>

是它的完整结构,实现的效果就是将远程库上的某一分支更新拉到本地,并且与本地指定的分支合并。有时候也会有一些简写,是因为 Git 会自动的在远程库和本地之间建立追踪关系,当然你也可以手动建立这样的关系,命令如下

git branch --set-upstream <本地分支名> <远程库名>/<远程分支名>

这些基本就是初级的 Git 使用和一个工作流,再次回看第一张图,我们要弄懂几点

  • 工作区

  • 本地库

  • 远程库

工作区和本地库之间的常用操作是 addcommitcheckout

本地库和远程库之间的常用操作是 fetchclonepush

工作区和远程库之间的常用操作是 pull

其他多是工作区的常用命令 mergerebase 等。

这些不需要特别记忆,常用用就自然而然的熟悉掌握了,更多的说明可以去官方查看。

一个问题,有时候在 push 时会出错,那么可以加入 --allow-unrelated-histories 参数即可。


> 可在 Twitter/X 上评论该篇文章