git版本控制
VCS(版本控制系统)
Git基础
关于git的详细介绍,可以参考官网的Git Book
Git安装
不同系统上git的安装流程 ,参照官方文档
Git配置
Git 自带一个 git config
的工具来帮助设置控制 Git 外观和行为的配置变量
config作用域
1 | git config --local #只对某个仓库有效,该命令只能在某个git repository内部使用,在仓库内部--local的配置优先级会大于--global的配置 |
配置用户信息
安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址。 这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改
1 | git config --global user.name "your_name" |
查看配置信息
1 | git config --list |
新建Git仓库
新建git仓库的两者场景
方法一:将已有的代码文件纳入git管理
1 | 进入已有的项目文件夹,执行: |
方法二:新建一个直接用git管理的新文件夹
1 | git init 文件夹名 #其会在当前目录下新建一个新的文件夹,并加此文件夹纳入git管理 |
git工作区域的理解
Git本地有四个工作目录,这四个工作目录之间的状态转换关系如上图所示
- Workspace:工作区,本地存放项目的文件夹
- Index/Stage:暂存区,用于存放临时改动的记录
- Repository:仓库区/版本库,里面会存放所有提交的版本数据
- Remote:远程仓库,比如Github上的仓库,我们可以通过相关命令把本地文件推送到远程仓库
我们通常直接操作的目录就是工作目录,然后将需要用git进行管理的文件或者文件夹,通过git add 文件名..
放入暂存区,通过git commit -m 标记
将暂存区文件提交至本地仓库,通过git push
将本地仓库推送到关联的远程仓库
git文件状态理解
版本控制是对文件进行版本控制,所以要明确当前操作文件所处的状态,在git中文件有四种状态
- untrack
- 未跟踪, 此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过git add 状态变为Staged
- modified
- 修改过,针对的就是已经登记在案的文件最近又发生了改动的情况,也就是说我们最近改过了某一个之前已经登记在案的文件
- committed
- 执行完commit之后,会在仓库中生成一个版本号(hash值),标志这次提交。之后任何时候,都可以借助这个hash值回退到这次提交。
- stage
- 这个时候已经执行过git add,但未执行git commit,但是用git diff已经看不到任何修改。
Git常见实操
场景一:从头创建一个新的仓库
在项目中新建文件以及文件内容修改
在C盘下创建目录git_learning,进入该目录执行git init
,可以看到生成了一个隐藏文件夹.git
,此时git_learning文件夹就成为了一个版本库,里面的文件都可以被git管理,即每个文件的修改、删除都能被git跟
在版本库(本地仓库)中添加新的文件
我们在git_learning文件夹下新建一个hello.txt
文件,里面内容为v000000
执行git add hello.txt
将该文件提交到暂存区
执行git commit -m xxx
将文件提交到仓库
每次执行git status
可以查看文件的状态
对hello.txt
文件进行修改,将v000000
改为v111111
我们可以通过执行git diff 文件名
的方式查看文件中到底改动了什么内容
知道文件修改内容之后,如果无误,可以重新对文件提交到暂存区和仓库
场景二:文件版本回退
前面我们对hello.txt文件进行了修改,前后一共提交了两次
现在我们对文件再次修改,将文件内容改为v222222
,并提交,我们前后对该文件修改了两次,该文件存在三个不同的版本
我们可以通过git log
查看历史提交记录
那么如果我们现在想把文件内容恢复到前面的某个版本,该怎么做?
git中回滚到历史版本的命令:
git reset --hard HEAD^
:回退到当前的上一个版本git reset --hard HEAD^^
:回退到当前的上上一个版本git reset --hard HEAD~n
:回退到当前的前n个版本git reset --hard 版本号
:可以精准回退到某个具体的版本记录
可以看到回滚之后,git log
看不到第三次提交的记录,那么如果我们想恢复到第三版记录(即内容为v222222),该怎么做?
我们可以先通过git reflog
查看版本号,然后回滚到指定版本
1 | Git 的 reflog 是指引用日志(reference logs)的简称,它记录了 Git 仓库中 HEAD 引用的变化历史。换句话说,reflog 记录了本地仓库的操作历史,包括分支切换、合并、重置等操作,即使在一些操作后出现了提交丢失或者分支丢失的情况下,通过 reflog 也可以找回之前的状态。 |
场景三:撤销文件修改与恢复被删除文件
我们修改hello.txt
文件,将其内容改为了v333333
,此时未执行其他命令,文件处于工作区,我们发现内容修改错了,想恢复到原始内容v222222
,该怎么做?
此时有三种解决办法:
- 直接修改
hello.txt
,将内容修改为原始内容- 此方法缺陷在于,如果原始内容较多,不记得了该怎么办?无法手动恢复
- 将错就错,执行
git add
、git commit
将文件提交仓库,再执行git reset --hard HEAD^
回滚到上一版本 - 执行
git checkout -- 文件名
,可以把文件在工作区的修改全部丢弃
我们在git_learning目录下新建一个文件test.txt
,然后将其提交到仓库,然后将该文件删除,那么我们如果想将该文件恢复应该怎么做?
- 方法1:
git commit
然后git reset
- 方法2:
git checkout -- test.txt
,可以直接在版本库中恢复此文件
场景四:本地仓库与远程仓库的关联
我们在GitHub上新建一个仓库git_learning
,可以通过如下操作,将本地仓库与远程仓库关联起来,并将本地仓库推送到远程仓库
1 | git remote add origin xxxxx.git #本地仓库与远程仓库 |
场景五:创建和管理分支
在我们实际代码开发过程中,一个项目可能会衍生出多个版本或者类型,但不同版本可能依赖的主体核心代码一致,只是不同版本的部分功能可能不一样,这个时候我们就需要将核心代码的部分生成多个分支用于支持不同版本程序的开发
或者同一项目多人协作,一般是不会直接允许在master(主分支)上进行开发,而是先在主分支上克隆一份,等个人开发完毕后再合并到主分支,这样可以避免代码污染等对主分支造成破坏
git branch -a
列出所有本地分支和远程分支
git branch
列出所有本地分支
git branch -r
列出所有远程分支
git branch 分支名
创建分支
git branch -d 分支名
删除分支
git checkout 分支名
将当前项目切换为指定分支
将当前新的分支推送到远程仓库(当前本地分支first推送到远程仓库的分支名也应该叫first)
git push --set-upstream origin first
在本地first分支上的修改不会影响本地和远程master分支上的内容
观察下面两张图,我们本地将分支切换回master,可以发现本地的tt.txt文件就会自动消失
如何合并多个分支?
在实际项目开发过程中,我们在自己分支上进行开发,最后要部署测试时,需要将自己分支代码合并到主分支应该怎么做?
我们首先执行git checkout master
切换回主分支
执行git merge first
将当前分支(主分支)与first分支代码合并
执行git push
将本地主分支代码推送到远程仓库主分支
场景六:团队协作与代码冲突解决
团队仓库如何进行git协作
团队仓库可以添加多名成员同时协作,注意此时各个成员在本地操作之前最好使用
git pull
将仓库最新代码拉取到本地,保证线上仓库与本地仓库的一致性
对于团队协作,我们的提交顺序:
- 刚开始进行项目开发时,使用
git pull
拉取更新 - 项目代码开发完毕之后,先
git add
、git comiit
到本地仓库 - push之前再使用
git pull
确保当前远程仓库所有更新都已经获取- 这样做是为了避免冲突,因为如果两个人同时操作了一个文件的变更,这时就会出现协作冲突,git此时不知道到底要使用哪一个人的变更,所以它会将两个人提交的不同部分标记出来
- 最后再
git push
将本地仓库推送到远程仓库
Git开源项目或者团队项目协作场景
如何进行Github团队项目的协作?
背景
我们准备两台不同的电脑,每台电脑登陆不同的github账号,模拟团队中的不同项目成员,由其中一个成员在github上创建一个公共仓库,然后邀请另一个账号(成员)协作。github创建团队项目team-work、并且邀请团队成员如下图所示
团队协作整个流程
一般团队协作各个成员是不允许直接在main(master)分支上直接操作,都是各自简历一个新的分支来进行
下面来模拟两个成员A和成员B如何协作团队项目
仓库最初的状态如下图所示,三个文件,以及test.txt中的内容如下图所示:
下面模拟团队协作,成员A的任务:创建新的文件testA.txt、在原始的test.txt最后一行添加I am member A
成员B的任务:创建新的文件testB.txt、在原始test.txt最后一行添加I am member B
然后两个成员各自提交到远程仓库对应的分支,然后由管理员B来进行分支合并和冲突问题解决
成员A
- 拉取项目到本地
git clone 远程仓库地址
- 在本地创建自己的分支
git checkout -b 自己的分支名
- 进行文件修改或者相关文件添加
- 提交到远程仓库
git push origin 自己的分支名
成员B
- 拉取项目到本地
git clone 远程仓库地址
- 在本地创建自己的分支
git checkout -b 自己的分支名
- 进行文件修改或者相关文件添加
- 提交到远程仓库
git push origin 自己的分支名
仓库合并
当前仓库状态:
成员可以在Github上创建pull request请求,让原作者(管理员人)看到你的修改,然后管理员会review代码文件,解决合并冲突,然后会执行Squash merge
将对应分支代码合并到main(master)分支
对于分支memberA的处理
对于分支memberB的处理
由于分支A与分支B都在同一文件test.txt中做了修改,所以会发生合并冲突,需要解决冲突才能合并
解决冲突,同时保留A和B的修改(删除文件中所有的分隔符即可)
此时main分支中包含了A和B两者提交和更改的所有记录
各个成员如何同步远程最新的代码
远程main(master)仓库更新后,各个成员本地git与远程仓库不一致,需要拉取远程main仓库最新状态,然后与本地自己的分支合并,同步最新状态
仓库主分支main中内容发生了变更,此时成员A需要同步远程仓库最新状态,并在最新状态上做修改,那么他应该怎么做?
- 本地切换到main分支
git checkout main
- 拉取远程仓库main分支最新内容到本地
git pull origin main
- 切换到自己的分支
git checkout memberA
- 将main分支与自己的分支进行合并
git rebase main
- 后续在最新状态上重复前面正常操作即可
参考资料
如何作为Collaborator在Github更新仓库(上传代码)
十分钟学会正确的github工作流,和开源作者们使用同一套流程
详解Git合并冲突——问题重现、原因及解决 “Automatic merge failed; fix conflicts and then commit the result.“