Git 是一个分布式版本控制与代码管理系统,用于自动跟踪文件和文件夹的历史变化,以及协调多人在同一项目上的协作开发,并在需要时进行版本回退和分支管理。


一、准备工作

1、安装Git

官网下载安装,把git-bash.exe所在的目录追加到系统变量的Path中。完成后,在任意文件夹内鼠标右键就能看到Git Bash Here,即输入Git命令行的地方。



2、上传公钥

任意位置鼠标右键,配置用户

git config --global user.name "gitee注册用户名"
git config --global user.email "gitee注册邮箱"

然后生成公钥

ssh-keygen -t rsa -C "gitee注册邮箱"

按默认设置一路回车,直到最后出现矩形图案,说明公钥已生成到C:\Users\用户\电脑用户名\.ssh文件夹中。复制文件夹内id_rsa.pub中的内容到gitee上,位置为设置>>SSH公钥。一份公钥可链接整个gitee账户的所有项目。




二、基于Git命令行运作

1、基于Git命令行上传项目

假设本地有一个Test文件夹,内涵诸多代码,视为一个项目。上传方法为:先在gitee上创建名为Test的仓库,然后在本地的Test文件夹内依次执行下列命令。

git init                 # 创建git环境(同一文件夹内只需执行一次,有【.git】即可)
git add . # 将本地仓库所有文件添加到git工作区,【.】代表所有
git commit -m 注释 # 将git工作区的内容提交到缓冲区 ,【注释】可以不用双引号,直接打中文
git remote add origin https://gitee.com/gitee用户名/Test.git # 链接远程仓库
git push origin master # 将缓冲区内容推送到远程仓库的master主分支


至此,Test项目就被推送到远程仓库。后面对本地工程做修改后,都需要重新依次执行第2、3、5行命令。

关于推送流程的示意图:

绿、黄、蓝、橘色部分:工作区、缓冲区、本地仓库、远程仓库



2、基于Git命令行解决冲突

如果有两个开发者A和B协作开发此项目,最大的问题就是读写冲突。其包括文件冲突(文件被增、删)与代码冲突(文件被修改),下面用一个例子来解释怎样解决。

以下面的代码工程为例,Test文件夹下有三个txt文件,每个txt文件的内容都是: 我是A

Test
1.txt
2.txt
3.txt


A最先按照上述步骤把项目push到远程仓库。B在自己的Test文件夹内通过下面命令pull下来最新版本的项目。

git init
git remote add origin https://gitee.com/gitee用户名/Test.git
git pull origin master # 获取远程仓库的项目

至此,A与B的代码完全一致。


A开始编辑,修改了1.txt(内容为:两行 我是A ),删除了2.txt,新增了4.txt(内容为:我是AA)。效果为:

然后用下面三行代码推送到远程仓库。

git add .          
git commit -m 注释
git push origin master

不报错,非常顺利,远程仓库内容也能跟随变更。



B此时开始编辑手里的代码,修改了1.txt(内容变为: 我是B ),修改了2.txt(内容变为: 我是B ),删除了3.txt,新增了5.txt(内容为:我是BBB)。

然后同样依次执行上面三行代码,报错,内容是系统发现远程仓库与本地仓库的原始版本不一致,即发生了冲突。(此时还不知道哪些文件发生了冲突)


首先需要把远程仓库合并到本地:

git pull --rebase origin master


此时可以查看哪些文件发生了什么冲突了(很重要的信息):

git status   # 先rebase合并再查看status,顺序不能颠倒

可以看出涉及到了4个文件(红绿色各两个),另外注意,自从rebase后,红框内所处分支已经从最开始的master变成了 master|REBASE 1/1,后面会复原。


打开本地仓库检查,此时,B手中的Test仅剩1、2、4、5.txt,具体为:

解释其现象:

  • 2.txt,内容仍为我是B ,虽说A已删除且已同步到远程仓库。但B执行合并后,自己的文件及其更改仍然保留。(对写者B是一种保护,对写者A无影响);

  • 3.txt,B刚刚已经删掉了,虽说A中有且已同步到远程仓库。但合并后仍然没有出现在B中。(对写者B是一种保护,对读者A没有影响);

  • 4.txt,B中没有,是A新增的。B执行合并后,保留A的变更追加到了B中。(对读者B无影响,对写者A是一种保护);

  • 5.txt,B新增的,A中没有。B执行合并后,仍然保留该文件以及自己的变更。(对写者B是一种保护,对读者A无影响);

以上皆为文件的增或删,属于文件冲突,更重要的是代码冲突,即1.txt

  • 1.txt,合并后被一些字符标记,git自动保留了每个人编辑过的痕迹。git授权当前的提交者决定保留哪些代码,同时需要手动删除<<==>>等标记符,这里选择保留所有人的代码。(这种决定需要开发者之间相互沟通,在公司中非常常见)。然后用下面的命令重新commit、继续rebase、再重新push即可:

    git add .          
    git commit -m 注释

    git rebase --continue # 这句会让 【master|REBASE 1/1】重新变为【master】。不执行这一句直接push仍然会报冲突错误

    git push origin master


检查gitee远程仓库,发现冲突已经按最后提交者的意愿解决:


后面,

  • 如果B需要继续开发,且赶在了A提交之前提交,那么就像刚刚的A一样非常顺利,直接提交成功不需要解决任何冲突。
  • 如果A需要继续开发,因为远程仓库已经与他手里的不一样了,他就需要像刚刚的B一样,手动解决代码冲突。

因此,总是靠后的提交者需要解决代码冲突,代码冲突是正常且非常常见的问题(IDEA支持一键解决)。文件冲突一般可以忽略,让Git自行解决。


https://www.bilibili.com/video/BV1JB4y1o7Vu




三、基于IDEA版本控制运作

1、基于IDEA上传项目

在IDEA中引入Git,设置中添加先前安装好的git.exe文件。

open打开Test项目后,点开功能栏的VCS,点击其中的Create Git Repository来初始化Git工作区。

create之后,IDEA页面发生变化:右侧工程代码文件变成红色(关于颜色后面说);VCS变成Git;且右侧多了三个Git的快捷按钮,分别是pull、commit、push。

创建远程仓库。与Git命令行不同的是,IDEA要求首次推送时Gitee上没有该仓库,它可以自动创建,如图所示,Git->Gitee->Share...

弹出一个界面,可以设定远程仓库的基本信息,无误后点击Share。

最后自定义要上传的文件,无误后点击Add,即可完成本地仓库的上传,即push推送。上传后代码文件由红色变为白色。

检查远程仓库,无误。


另外,后面再创建新代码文件时,最好点击这个Add按钮,他能自动把该文件放置到Git工作区,从而自动将其加入版本控制,其颜色也就能从红色变为绿色。

如果后续对该项目又有了其他修改(修改后文件变成蓝色),想最后重新提交所有文件到远程仓库。在IDEA中只需点击三个按钮即可。

首先点击上面提到的Git快捷键中的第2个(commit动作):

commit后会在左侧显示发生变化的文件(Change部分),然后添加本次提交的注释(必填),最后点击右下角的Commit and Push(若报异常就再次点击)。

下一个页面再点击一下Push,即可完成本地仓库到远程仓库的推送。


最后补充代码文件颜色变化的详细说明:



2、基于IDEA解决冲突

就像第二.2部分提到的文件冲突和代码冲突,如果远程仓库早先已被人更新过,那么在最后一步点击Push推送时,就会报下面的冲突。


IDEA支持按键式合并来解决冲突。这里选择Merge和Rebase都能进行合并,我一般选择后者。点击Rebase后IDEA会自动分析哪些文件发生了哪些冲突,就像下图中绿色框的部分,可以看出1.txt发生了代码冲突,自己和远程仓库都进行了Modified。如果多个文件发生了冲突会逐一列出,这里仅以1.txt举例。


双击列出的文件可进入查看具体的冲突。

可以看出左侧栏为自己的版本(只读);右侧栏为当前远程仓库的版本(只读);中间栏是动态的,代表合并后的版本(可读可写)。而怎样合并取决于自己,点击<<>>都点击可实现不同的效果,这里都点击,即都保留,最后Apply,冲突解决。


在返回后的页面上重新点击Commit and Push,然后再下一个页面上继续点击Push,即可完成本地仓库到远程仓库的推送。


检查远程仓库,多人的修改都得到了保留,无误。




四、将多分支应用于我们的多项目

gitee中默认的主分支为master,可自行创建其他分支。其他分支的本意是服务于master的,比如电商项目中将支付、商品、购物车模块分离给各个开发组,各自开发完成之后自主合并到master。


1、适用于我们需求的设想

为适应我们的需求,打算让其他分支各自独立,各自做存储与代码版本控制,永不合并到master。


以DWF后端程序为例,master维护一版基础性代码,同时基于此为多个地区的项目开辟多个分支,比如chengdu、beijing、tianjin等,如下图所示。每个子分支维护一份地区的DWF后端项目,在推送时分开推送,有冲突时也是分开解决。


同理,前端程序、TCP-Server、EDA各自占用一个仓库,每个仓库中也是以master为基础,以地区为依据开辟多个分支来分开管理。


至于多个开发者,每个仓库的管理员分别邀请即可,邀请进来的开发者有权限对本仓库的所有分支进行开发



2、基于Git命令行对多分支项目进行管理

IDEA同样支持分支的切换,但不同开发者的IDEA编辑器版本不同,其方法也略有差异,这里仅以Git命令行为例进行说明。


1)创建远程空分支

新建的分支都是基于master的,与master一致。我们的需求需要新分支为空,然后上传与master分支不一样的内容,所以需要清空新建的分支,或者直接创建空的分支。

  • 后者很简单:创建该仓库时master分支是空的,这时候开辟新分支,也将是空的。

  • 前者:先切换分支,然后执行下面分支进行清空:

    git rm -rf *       		# 或者【git rm -r --cached .】先清掉本地分支的内容	# 只删掉指定文件:【git rm -r --cached 文件名】
    git commit -m 'Empty the branch' # 提交空分支
    git push origin 分支名 # 如果出错可以强制推送git push -u origin 分支名 -f


2)提交代码

假设远程仓库中已经建立好了各地区的空分支(如上图所示),本地也已有Test项目,进行推送时需要依次执行下列命令。

cd Test

git init
git add .
git commit -m 注释

git branch chengdu # 在本地创建同名分支(必须在add、commit之后执行此句才有效,否则git还未有branch的概念)
git checkout chengdu # 切换分支

git push origin chengdu # 将缓冲区内容推送到远程仓库的chengdu子分支


3)解决冲突

关于解决冲突,和二.2一样,只是所处的分支变了。

git pull --rebase origin chengdu
git status

git add .
git commit -m 注释
git rebase --continue
git push origin chengdu