了解Git
集中式版本控制
- 开发人员通过客户端连接到这台服务器,取出最新的文件或者提交跟新。
- 主要特点是:单一的集中管理的服务器,保存所有文件的修订版本。
分布式版本控制
- 开发人员通过客户端把代码仓库完整的镜像(克隆)下来,包括完整的历史纪录;
- 任何一处协同工作的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复;
- 每一次克隆操作,实际上都是一次对代码仓库的完整备份。
简单来说集中式是将整个代码仓库放到服务器,而分布式是每个开发人员本地都有一个代码仓库,可以在本地提交代码,最后把本地的代码仓库同步到相对应的代码服务器就行。
Git配置
安装完git之后,第一件事情就是设置用户名和邮件地址。
git config --global user.email "xxx"
git config --global user.name "xxx"
配置信息会存在于.gitconfig中,在我们提交代码代码的时候,会自动读取该文件中用户信息,它们会写入到每一次提交中。
Git仓库的获取
如果是新项目,是没有远程仓库的,需要创建一个本地仓库。
git init //初始化一个空的Git存储库
如果项目已经有远程仓库,直接clone下来就行,可能会存在验证的问题,可能需要做一些配置,例如用户名/密码/ssh。
git clone <远程仓库地址>
存在一个私人远程仓库:
- HTTPS: gitee.com/xxx/learn_g…
- SSH: git@gitee.com:xxx/learn_git-demo.git
git clone https://gitee.com/zzzzzccyy/learn_git-demo.git
//或者
git clone git@gitee.com:xxx/learn_git-demo.git
私有仓库会对我们的身份进行验证
- 方式一:基于HTTP的凭证存储;
- 方式二:基于SSH的密钥。
基于HTTP的凭证存储
HTTP协议是无状态的连接,所以每一次连接都需要用户名和密码。
如果是Mac电脑,git有一种osxkeychain模式,它会将凭证缓存到你的系统用户的钥匙串中(加密)。 如果是windows系统,安装一个Git Credential Manager for windows的辅助工具。(安装git时会默认下载此工具)(microsoft.github.io/Git-Credent…
可以在控制面板中删除凭证
基于SSH的密钥
生成对应的公钥和私钥
ssh-keygen -t 加密方式 -C "your email"
ssh-keygen -t ed25519 -C "your email"
执行完之后会生成公钥和私钥,把公钥配置到远程服务器中。
Git文件的状态划分
未跟踪(untracked):默认情况下,git仓库下的文件也是没添加到git仓库中的,需要通过add命令来操作。
已跟踪:添加到git仓库的文件处于与跟踪状态,git可以对其进行各种跟踪管理。
- staged:暂缓区的文件状态;(创建新的文件,或者之前文件有新的改动,执行git add之后,得到的状态就是staged)
- modified:修改某个文件之后,会处于该状态;(原本就存在在git仓库中的文件发生改动之后的状态)
- unmodified:执行commit命令,可以将暂缓区状态的代码提交到git仓库。
检测文件状态-git status
文件添加到暂缓区- git add
git add .
//或者
git add <具体文件名>
跟踪新文件或者已经在跟踪的文件发生修改了也需要重新add到暂存区中。
Git忽略文件
创建一个.gitignore文件,在里面添加不想被跟踪管理的文件。(在.gitignore中的文件不会添加到本地仓库中。)
在实际开发中,这个文件通常不需要手动创建,在必须的时候添加自己要忽略内容即可。
文件更新提交 -git commit
git commit -m "提交信息"
查看提交的历史- git log
git log
git log --pretty=oneline
git log --pretty=oneline --graph
版本回退- git reset
如果想要进行版本回退,我们需要先知道目前处于哪个版本,git通过HEAD指针记录当前版本。HEAD指针可以把它看成该分支上的最后一次提交的快照。可以通过HEAD来改变git目前的版本指向。
//回退到上一个版本是HEAD^
git reset --hard HEAD^
//回退到上上个版本是HEAD^^
git reset --hard HEAD^^
//回退到指定版本可以通过指定某个commitId
git reset --hard commitId
Git标签
对于重大的版本我们常常会打上一个标签。
//创建tag
git tag v1.0.0.0
git tag -a v.1.0.0 -m "附注标签"
//默认情况下git push 命令不会把本地打的标签push到远程服务器上,需要
git push origin v.1.0.0
//检出tag,会回到v.1.0.0
git checkout v.1.0.0
//通常我们在检出tag的时候还会创建一个分支
git add .
git commit -m ""
git tag v1.0.0.0
git push origin v.1.0.0
远程仓库的交互
- 从远程仓库clone代码到本地
git clone <远程仓库路径>
- 将本地代码push到远程仓库
//默认情况下是将当前分支(master),push到origin远程仓库中
git push
git push origin master
- 从远程仓库获取最新代码到本地
默认情况下是从origin中获取代码
git fetch
git fetch origin master
//获取到代码后,默认并没有合并到本地仓库,需要通过merge来合并
git merge
git merge origin/master
- 从远程仓库获取最新代码并合并到本地仓库
//git fetch + git merge
git pull
远程仓库
查看远程仓库地址:比如我们之前从github上clone下来的代码,它就有自己的远程仓库,查看远程仓库的名字。
git remote
git remote -v
如果是我们在本地初始化初始化的git项目,需要让本地的仓库和远程服务器建立连接,在本地仓库添加远程地址仓库: git remote add <仓库名字>
git init
git add .
git commit -m "初始化项目" //把代码添加到本地仓库中
git remote add origin https://gitee.com/xxx/learn_git-demo.git
//此时本地仓库已经和远程仓库建立好连接了,但是它并不知道本地仓库的哪个分支在和远程仓库的哪个分支建立连接
//给本地仓库设置上游分支
git branch --set-upstream-to=origin/master
git fetch origin master //把远程仓库的master分支内容拉到本地仓库
//但是本地仓库和远程仓库是两个老不相干的,并没有共同的祖先,是不允许合并的。
git merge --allow-unrelated-histories //此时已经把本地仓库和远程仓库的代码进行合并
//把本地代码push到远程仓库(origin/master)
git push
如果我们是直接是从远程仓库clone下来的代码,直接push就行
git clone <远程仓库地址>
//其实它本地的master分支已经跟踪了远程的master分支,直接push就行
git pull
git分支
git branch <分支名字>
git checkout <想切换到的分支名字>
//创建分支并切换
git checkout -b <分支名字>
为什么需要分支?
开发某个项目,在默认分支master上进行开发。 在实现项目的功能需求,需要不断提交。并且在一个大的版本完成时,在发布版本上,打上一个tag备份。
- b打上tag,并且已经发布线上供用户使用。
- 此时项目已经开发到了e,用户使用发现线上存在bug。
- 此时需要某个程序员回到tag v1.1.1版本(git checkout v1.1.1),创建新的一个分支,进行bug修复。
- 修复bug之后,其实c、d、c中都存在bug的,需要将hotfix和master分支合并。回到master分支,执行git merge hotfix 合并。
git init
git add .
git commit -m "初始化项目"
git commit -a -m "a"
git commit -a -m "b"
git tag v1.0.0
git commit -a -m "c"
git commit -a -m "d"
git commit -a -m "e"
//以上的是master分支
git checkout v1.0.0
git checkout -b hotfix
git commit -a -m "hotfix1"
git commit -a -m "hotfix2"
git tag v1.0.1
//以上的是hotfix分支
//把修复bug的代码合并到master分支
git checkout master
git merge hotfix //有时候会有冲突
//解决完冲突
git add .
git commit -m "合并hotfix分支"
git push
git的工作流
git的远程分支
存在一个远程仓库git@gitee.com:zzzzzccyy/learn_git-demo.git,只有一个main分支,本地仓库是master分支
添加远程仓库
git init
git add .
git commit -m "初始化"
git remote add origin <xxx>
git fetch origin main
git branch --set-upstream-to=origin/main //拉去下来的仓库名字叫origin/main分支
git merge --allow-unrelated-histories
git config push.default upstream
git push
将本地分支推送到远程仓库
- 本地仓库存在master和dev分支
- 远程只有main分支
...
//以上都是在本地dev分支开发,但是上流分支还是main分支
git push origin dev //此时远程有dev分支
git branch --set-upstream-to=origin/dev
git push //现在push到远程仓库的是dev分支的内容
搭建一个全新的项目仓库
存在一个远程仓库,只有master分支。
方案一:
git clone xxx
//在clone下来的文件夹中开始搭建项目
git add .
git commit -m ""
git push
方案二:
//创建一个本地仓库(master分支)和搭建本地项目
git init
git add .
git commit -m "初始化项目"
//本地仓库和远程仓库建立连接
git remote add origin https://gitee.com/xxx/learn_git-demo.git
//让本地的master分支和远程的master建立连接,变成我们的上游分支
git branch --set-upstream-to=origin/master
//把远程仓库的master分支内容拉到本地仓库
git fetch origin master
//但是本地仓库和远程仓库是两个老不相干的,并没有共同的祖先,是不允许合并的。
git merge --allow-unrelated-histories //此时已经把本地仓库和远程仓库的代码进行合并
//把本地代码push到远程仓库(origin/master)
git push
如果本地仓库只有main分支,而远程仓库只有master分支
//创建一个本地仓库和搭建本地项目
git init
git add .
git commit -m "初始化项目"
git remote add origin https://gitee.com/xxx/learn_git-demo.git
git branch --set-upstream-to=origin/master
git fetch origin master
git merge --allow-unrelated-histories
//默认push.default是simble,找的是当前本地仓库分支相同的远程分支,如果不同就会报错
git config push.default upstream
git push
git branch --set-upstream-to=origin/master
git fetch origin master
git merge --allow-unrelated-histories
git config push.default upstream
//如果觉得以上步骤太复杂可以执行
git checkout --track origin/master
//如果本地仓库没有main分支,会自行创建并自动跟踪origin main分支
git push
作为组员
git clone <远程仓库地址>
//假设默认clone下来的是main分支,但是所有开发是在dev分支进行,需要进行分支切换,可以执行
git checkout --track origin/dev
//或者执行
git checkout dev
//进行开发
git add .
git commit -m "xxx"
git pull
git push