使用Git进行团队协作开发的一个虚拟场景描述

背景

此时有一个3人团队协作开发一个项目group-git-study,团队成员分别为A,B,C,其中C为团队主导人及远程仓库的管理员,A,B分别为开发者。

首先团队主导人C需要在Gitee上创建一个新的仓库,命名为GroupGitStudy,并根据需求选择初始化仓库以及相关模板文件,注意在该场景中,我们将使用master/develop分支模型进行管理。创建完成后,我们将得到一个包含模板文件的新仓库。此时,可以邀请团队成员A,B加入成为仓库的开发者。注意:某些情况下develop分支如果是一个空分支,则需要在正式开发前先保持master分支与develop分支的同步。

开始开发新的功能模块

假设每个成员现在已经接到了分配的任务,成员A此时接到任务需要开发一个新的功能模块“ ls ”,则此时A应当从develop分支创建一条新分支feature-a并在新分支上进行开发。应当极力避免的是直接在master上进行开发,因为master主分支上应该只保留经过稳定测试的版本。

当成员A在新分支上完成开发任务后,应该切换到develop分支并将新功能分支的更改合并过来,推送develop分支,而不应该直接推送feature-a分支

在每次开发新的功能模块之前,一定要先拉取最新的改动!

完成开发后,一般情况下选择保留新的本地分支以备未来可能的功能需求改动,有时候如果创建的临时分支仅开发一个小功能,也可能会考虑删除该分支以保持本地仓库的整洁。

ls这个模块就交给你了哈

好的,我已经写好提交上去了~

仓库里怎么多了一个feature-dog分支?!

git clone git@gitee.com:userA/group-git-study.git #首先成员A需要克隆远程仓库到本地
git pull #在每次开始开发之前先拉取最新改动是一个好习惯,避免产生无意义的冲突

git checkout -b feature-a develop #从develop分支创建一个feature-a分支进行新功能的开发

... #进行一些开发,如创建ls.c ls.h等相关文件

git add . #完成新功能模块阶段性的开发,添加文件到暂存区
git commit -m "add ls" #提交更改,应当在commit消息中简洁明了的说明做了哪些更改
git switch develop #注意要切换回develop分支!不要直接推送用于开发新功能的本地分支!
git merge feature-a #将feature-a分支上的的更改合并到当前分支,并创建一个新的提交记录
git push origin develop #将develop分支推送到远程仓库

如何临时修复BUG

假设此时master分支上的一段代码出现了一个非常难以发现的小疏漏,一名未知团队成员将main函数错误的书写为了mian导致代码无法正常编译,仓库管理员C发现了这个问题,开始进行紧急bug修复,此时可以考虑从master分支上创建一条临时分支hotfix-main,并在该临时分支上进行修复、测试,最终合并到主分支上,同时记得并将develop分支同步。

在该场景中使用非快进合并提交的目的是为了保留一个明确的合并记录,以指示进行了一次bug修复,也可以直接使用合并,可以根据具体需求考虑。

git checkout -b hotfix-main master #从master分支创建一个hotfix-main分支进行bug修复

... #进行bug修复及测试

git switch master #切换到master分支
git merge --no-ff hotfix-main #合并hotfix-main分支,使用非快进合并提交
git tag v0.1.2 #创建一个标签,来标记一个新的重要稳定版本
git push origin --tags master #推送master分支及标签到远程仓库

如何解决冲突?

A,B完成了各自的功能模块的添加,此时A,B想要将自己的的模块功能添加到主函数逻辑中,于是两人同时对main.txt进行了编辑,A添加了一段功能:add function1 by A,B添加了一段功能:add function2 by B。但是此时由于A完成代码的速度较快,于是A进行了一次提交并推送到了远程仓库,而在此期间B仍在完善功能代码阶段,B并不知道此时远程仓库的代码已经进行了更新。待B完成代码后,开始尝试提交并推送,此时就会发生冲突的情况。
  • A先修改并推送了main.txt文件,由于A最先推送,且在此期间远程仓库并未发生更新,因此此时不会发生冲突。
git checkout -b feature-a develop
git add main.txt
git commit -m "add funcA in main.txt" #在main中添加了一个新功能的调用

git switch develop #先看看develop分支有无更新
git pull origin develop #拉取远程仓库develop分支的最新代码
git switch feature-a #切换回feature-a分支
git merge develop #尝试合并develop分支的代码,此时没有发生冲突

git switch develop #注意不要直接推送feature本地分支!
git merge feature-a #合并feature-a新功能模块
git push origin develop #推送到远程仓库

​ 成员A的操作顺序是一种推荐的方法,先切换到develop拉取更新,在合并develop分支到feature-a分支,如果有冲突则可以在 本地分支上解决冲突,避免出现本地存储的develop分支状态已经被破坏,冲突一时间又无法解决导致的混乱情况。

  • B后修改并尝试推送 main.txt文件。在这里我选择描述一种比较常见且简便的推送方式:B事先忘记或来不及拉取远程develop分支的更新,直接在本地合并并进行推送导致冲突。

为什么我提交不上去代码?我重新拉了下,一通操作我刚改的代码没了!

可能我刚才提交了一次,你没更新。。。

git checkout -b feature-b develop
git add main.txt
git commit -m "add funcB in main.txt"

git switch develop
git merge feature-b
git push origin develop #推送到远程仓库时发生冲突

此时会发生冲突,按照提示,远程仓库存储了我们本地并未更新的代码,我们需要在推送前拉取远程仓库的更新。

git pull #此时默认执行git fetch + git merge
git pull --rebase #如果不想留下一个额外的合并提交,想要更线性的提交树可加上该参数
git status #可以查看冲突的文件并逐个编辑

可以根据终端输出的信息得知:git尝试自动merge合并远程最新的main.txt与本地的文件,但是发生了合并冲突,自动合并失败,需要用户自行修改冲突行并重新提交。

cat main.txt #可以使用cat快速查看
vim main.txt #或者直接使用vim打开冲突文件并编辑

此时git会自动对发生冲突的行添加上面的标记文本,可以使用cat指令快速预览文件的变化。当我们使用vim编辑冲突文件可以通过搜索冲突标记 <<<<<<<,以快速定位冲突位置。 <<<<<<< HEAD 后表示的是头部分支或基本分支的更改, =======是一个分割符,而 >>>>>>> 分支名/提交ID上面表示的是在比较分支上编写的更改内容。此时我们便可以决定保留哪些更改,注意此时我们需要删除git自动生成的冲突标记符。最后我们便可以重新添加解决完冲突的文件并提交。

git add main.txt
git commit -m "solve merge conflicts"
git push origin develop #解决完冲突后便可以提交并推送

结语

上面描述了一个简单的小团队使用git进行团队协作开发的虚拟案例中各种情况的操作方案,使用了简单的master/develop开发模型。实际公司的开发场景下可能有更加复杂的提交树管理方法,如fix,release,feature等更多分支模型,但个人认为对于我们这个简单的网盘项目的开发,双分支模型应该足够满足大部分需求了。作者本人也并没有过多团队协作开发的经验,文章如有疏漏请各位大佬不吝赐教,可以随意在评论区指正或提出修改建议!

Git常用基础指令个人整理

  1. 创建新仓库并查看当前状态
git init #在当前目录初始化git仓库
git status #查看当前仓库状态

git config --global user.name "名字" #第一次使用需要设置用户名和邮箱
git config --global user.email "邮箱地址"

git log #显示当前分支的提交历史
git log --graph --decorate --oneline --abbrev-commit #豪华版
git log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit #超级无敌豪华版
  1. 远程仓库相关操作
git clone <远程仓库地址> #克隆远程仓库
git remote add <远程仓库名> <远程仓库地址> #连接远程仓库,远程仓库名一般是origin
git remote -v #查看所有远程仓库
git push <远程仓库名> <本地分支名>:<远程分支名> #推送指定分支到远程仓库,默认名称一般是origin

git push origin --delete <要删除的远程分支名> #删除远程仓库上的一个分支,本地仍然可以找到该分支
git push origin :<要删除的远程分支名> #删除远程仓库上的一个分支,本地仍然可以找到该分支
git remote update origin --prune #有些时候可能会通过git远程仓库的网页删除分支,此时可能出现vscode里显示的远程分支与实际远程分支不同步的情况,可以用上述命令解决。
  1. 添加文件并提交
git add <文件名> #添加指定文件
git add . #添加所有文件
git reset HEAD <文件名>  #撤销暂存区的更改并保留工作区的改动
git restore –staged <文件名> #撤销暂存区的更改并保留工作区的改动(新指令),可以一次取消暂存多个文件

git diff HEAD #显示工作区与最新提交之间的差异
git diff <文件名> #查看指定文件的差异

git commit -m "提交信息" #提交并附带信息
git commit --amend -m "新的提交说明" #修改最后一次的提交说明
  1. 分支相关操作
git branch -vv #显示本地分支列表以及它们关联的远程分支的跟踪情况,当前分支前会标记一个 * 符号
git branch feature-a #创建feature-a分支
git branch -d feature-a #删除feature-a分支

git checkout develop #切换到develop分支
git switch develop #切换到develop分支(新指令)

git checkout -b feature-a develop #从develop分支创建一条新分支feature-a并切换过去
git switch -c feature-a #从当前分支创建一条新分支feature-a并切换过去
  1. 更新与合并
git fetch #获取最新改动,下载到本地仓库中但不自动合并到当前工作分支
git pull #从远程仓库拉取最新改动并尝试自动合并,默认情况下即git fetch + git merge

git merge feature-a #将feature-a分支上的的更改合并到当前分支,会创建一个新的提交记录
git merge --abort #取消合并操作(仅在本地有效)
git rebase master #将当前分支上的提交逐个应用到master分支上
git rebase -i master #打开一个交互式rebase编辑器

git diff <分支1> <分支2> #查看两个分支的差异
git reset --hard origin/master #丢弃所有本地改动与提交(仅在本地有效)
git reset --hard <提交ID> #将分支重置到合并之前的提交(仅在本地有效,如果已经推送不要这么操作!)

Git懒人设置

  1. 使用打开个人家目录下的 .gitconfig 文件
  2. 复制以下代码
[alias]
    co = checkout
    ci = commit
    br = branch
    st = status
    last = log -1
    lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
  1. 放到 .gitconfig 文件末尾
  2. 此时你就可以快乐的使用简短的命令了

这个lg指令对于使用纯命令行的程序员特别友好,可以清晰的看到提交历史,有时候可能比图形化界面还要直观。

(❁´◡`❁)编程笨蛋萌新也想折腾博客!
最后更新于 2024-05-20