🔥keyipatience:个人主页
🎬作者简介:C/C++后端开发学习者
🌟专栏传送门:《c++》《linux》《c++高阶数据结构》《c++数据结构与算法》《前端学习》
《Git》
⭐️patience is key in life
Git 多人协作
核心规范:master 主分支尽量不直接修改,保持稳定;新功能全部在 dev 开发分支上做,多人在dev 协作
前期准备(模拟两个开发者)
- 两个人都
git clone同一个远程仓库到本地(Linux、Windows 模拟两个人) - 远程仓库先在网页上新建远程分支
dev,起点是 master - 本地拉取远程最新信息,拿到这个新的 dev 分支
git pull # 获取远程新分支信息 git branch -r # 查看所有远程分支,能看到 origin/dev git checkout -b dev origin/dev # 创建本地dev,并关联远程origin/dev执行完后再git branch -vv,可以看到本地dev已经和远程origin/dev建立了关联
如果没有建立关联单单只创建了本地分支,可以用
//单独建立关联 git branch -u origin/dev dev //或直接push 的时候一次性绑定 git push -u origin dev此时两个人本地都有 dev,并且和远程 dev 建立追踪关系,以后就在 dev 上写代码。
单人在 dev 开发、推送到远程
# 1. 修改文件 vim file.txt # 2. 暂存、提交 git add file.txt git commit -m "first function" # 3. 推送到远程dev分支 git push origin dev推送成功:远程 dev 更新,别人后面 pull 就能拿到你的代码
多人修改同一个分支(dev),冲突场景
场景A
直接改代码 → commit → push 问题根源:开工一开始,本地就已经落后远程,从一开始版本就不对。 一 push 直接报错分叉。
B (Linux版本) / A --- \ C (Windows版本)具体过程:
1.windows在file.txt新添 windows coding,然后push
2.Linux没有事先pull,而是同样在file.txt新添linux coding
push报错因为远程有新东西,本地版本落后并且你自己也写了新提交,分叉了,必须先 pull 合并,才能 push。
3.执行pull
3种方式(推荐方式1merge合并)
## git config pull.rebase false 简写:git pull --no-rebase 永久设置,设置完之后,以后直接敲 git pull 就自动 merge,不再报这个错 git config pull.rebase false- 逻辑:做合并(merge),把远程分支合并进本地
- 提交历史:会新增一条专门的合并 commit,历史分叉保留,能看清两边各自做了什么
## git config pull.rebase true rebase 变基 命令简写:git pull --rebase- 逻辑:不合并,把你本地自己的提交,摘下来,放到远程最新提交的后面
- 提交历史:不会产生合并 commit,历史是一条直线
## git config pull.ff only 仅快进 命令简写:git pull --ff-only- 只允许「快进更新」,一旦发现分叉,直接拒绝 pull,啥也不干,报错退出
- 不会 merge、不会 rebase
这里我们推荐第一种方式merge合并
4.执行git config pull.rebase false,后再git pull,可以看到file.txt文件已经有冲突了,说明pull成功了
5.vim file.txt 手动解决冲突,保留我们想要的代码
6.三板斧
场景B:
事先pull下来了,再在此基础上修改
先拉取远程最新代码到本地合并
git pull第一种(最常见)无分叉。远程有新代码,你本地没有自己新的提交。 直接快进更新(Fast-forward)成功,没有冲突也不会弹nano页面。 拉完,本地和远程一模一样,你放心写代码。
第二种远程没有任何更新。 git pull 啥都不干,直接提示Already up to date,意思:已经是最新的。
第三种 远程有新代码,你本地也有上次遗留的 commit(上次写了没 push)两边分叉了。
→ C (远程,Windows刚推上去的) B → D (你Linux本地,上次commit但是没push的)具体过程:
1.windows创建file3.txt,add->commit->push
2.linux创建file2.txt,add->commit(没有push)
3.此时linux执行git pull
简单流程
Ctrl+O- 敲回车
Ctrl+X
做完之后,合并提交就生成好了,回到命令行。
其实刚刚上面演示的是无冲突分叉,分叉也可以分为2种有冲突和无冲突
1.文件没有冲突Git 能自动把文件合并好,准备好一条合并提交,打开 nano 让你确认提交信息。
即这个界面:
2.有冲突(要我们自己vim并决定保留哪些代码) Git 发现file.txt两边改了同一处,它不知道怎么合并,自动合并失败,暂停下来。 合并提交还没有生成!它等着你:手动改文件、解决冲突 →git add→ 再git commit->git push
弹这个界面
pull
(0)
Already up to date(1)没有分叉直接fast-forward
(2)无冲突分叉,弹nano
(3)有冲突分叉,vim手动保留
总结:
- 还没写代码:优先先 pull,再开发(好习惯)
- 已经改完、已经 commit 了:只能 pull 合并,处理分叉冲突
功能全部开发完成:dev 合并回 master(上线)
切到 master,拉取最新 master,保证本地 master 是最新
git checkout master git pull切回 dev,把 master 合并进 dev(提前在 dev 解决 master 和 dev 之间的冲突)
git checkout dev git merge master # 这里如果有冲突,在dev解决完、提交切回 master,把 dev 合并进 master
git checkout master git merge dev把合并后的 master 推送到远程
git push origin master收尾:删除没用的 dev 分支
dev 的功能已经合并进 master,任务完成,可以删掉分支:
- 网页端:直接在 Gitee/GitHub 页面删除远程 dev 分支
- 命令行删除远程分支:
git push origin -d dev补充:
git branch -r:只看远程分支- git branch -a:看远程和本地全部分支
- git branch -vv:看远程分支和本地分支的关联关系
- 追踪分支:
git checkout -b dev origin/dev建立关联,之后 pull/push 不用每次写远端地址
Feature 分支多人协作
核心范式:主分支 master 保持稳定;每个需求单独开 feature 分支开发,互相隔离;做完再合并回 master
两个人各自新建自己的 feature 分支(你 feature-1,小伙伴 feature-2)
# 查看本地分支 git branch # 新建分支并且直接切换进去 git checkout -b feature-1然后写代码、提交、推远程:
vim function1 # 写需求代码 git add function1 git commit -m "add function1" git push origin feature-1 # 只推送feature-1这个分支!不碰master小伙伴那边,同样操作:
git checkout -b feature-2 vim function2 git add function2 git commit -m "add function2" git push origin feature-2在本地,你看不见他的 function2,他看不见你的 function1,推送各自分支,互不冲突!
查看两个分支各自独立的提交记录
- feature-1 分支:只存在
function1文件,这条分支领先 master 1 个提交 - feature-2 分支:只存在
function2文件,这条分支领先 master 1 个提交
这就是分支隔离: 切换到哪个分支,工作区就加载哪个分支对应的全部文件。 切 feature1 → 看到 function1;切 feature2 → 看到 function2;切 master → 两个文件都没有。
正常开发节奏:两个人在自己分支安心写需求,互不影响,直到开发完成准备合并。
现在小伙伴没法继续写了,你要接手帮他在 feature-2 上面继续开发
# 拉取远程所有分支的信息 git pull执行完,远程的origin/feature-2信息已经被本地 Git 知道了
# 查看所有分支(本地+远程追踪分支) git branch -a # 会列出 remotes/origin/feature-2remotes/origin/feature-2代表:远程上的 feature-2 分支,只是一个追踪标记,你还没有本地 feature-2 分支。
# 新建本地feature-2分支,并且直接绑定上游远程origin/feature-2 git checkout -b feature-2 origin/feature-2- 在 feature-1 看到 function2.txt:是pull 合并过来的结果
- 切到 feature-2 看到 function2.txt:是这个分支原生就创建了这个文件,属于 feature-2 自己的提交
切换成功,ls 可以看到 function2 文件,现在你就在小伙伴的分支上了,可以接手开发:
vim function2 # 修改代码 git add function2 git commit -m "modify function2" git push origin feature-2 # 推送到远程feature-2分支小伙伴回来,拉取你帮他更新后的 feature-2。然后小伙伴就可以接着开发了
git pull //没有绑定远程的话再 git branch --set-upstream-to=origin/feature-2 feature-2现在功能开发完毕,把 feature 分支合并回 master 主分支。
合并前,先把 master 最新代码合并进自己的 feature 分支,冲突在 feature 分支解决,不要在 master 上解决冲突
小伙伴先合并 feature-2 进 master
# 1、切回master,拉最新master,保证本地master和远程master一致 git checkout master git pull # 2、切回自己的feature-2分支,把master合并进feature-2(先同步主线最新代码) git checkout feature-2 git merge master # 3、切回master,合并feature-2 git checkout master git merge feature-2 # 4、push master到远程 git push origin master合并完成,远程 master 现在带上了 function2 文件
轮到你合并 feature-1 到 master
因为现在 master 已经被小伙伴更新了,里面有 function2 了!你不能直接合并,必须先把 master 的新代码同步到你的 feature-1
# 步骤1:切master,拉取最新master(拿到小伙伴合并进去的function2) git checkout master git pull现在本地 master里面已经有 function2
# 步骤2:切回你的feature-1分支,把master合并进feature-1 git checkout feature-1 git merge master页面里面这次没有冲突,自动合并成功,ls 你会看到 feature-1 里面同时有 function1、function2
# 步骤3:把同步好master的feature-1,推送到远程feature-1 git push origin feature-1 //其实上一步把 master 的更新合并进本地 feature-1,这一步执行完你的本地 feature-1 分支,历史已经变了,和远程 origin/feature-1 不一样了为什么还要 push feature-1?
实际开发中 master 很多时候是网页 PR 合并(不是本地 merge),要保证远程 feature 分支是最新、已经和主线同步好的状态,方便评审。
# 步骤4:切回master,合并feature-1分支 git checkout master git merge feature-1# 步骤5:推送master到远程 git push origin master推送后,远程 master 同时拥有 function1、function2 两个文件,两个需求全部上线到主线。
收尾:feature-1、feature-2 需求已经全部合并进 master,分支使命结束,可以删除(本地 + 远程都可以删)