一、git简介
git是什么
(1)git是分布式版本控制系统,用来记录一个或者若干文件内容的变化;
(2)如何理解分布式版本控制系统呢?
当我们在编辑某个文档时,想修改文档的某个地方,但又害怕修改后没有达到预期结果,想恢复修改前的版本,此时可能就是将文档另存为,不断的有问题,不断的另存为操作,到最后发现会有一堆文档;或者需要同事协助帮忙填写文档的某一部分,在一天后,自己也修改了文档的内容,同事也修改了文档的内容,然后必须要把自己修改的内容和同事的部分合并,好复杂。
分布式版本控制系统就是帮助我们解决版本控制、合并问题。
git与SVN的区别
SVN是集中式版本控制系统,git是分布式版本控制系统;主要有以下区别:
(1)SVN必须联网才可以使用,git有本地仓库,无网络时也可以提交,待有网络时再push到服务器;
(2)主要区别是本地是否有完整的版本库历史;假设SVN服务器没了,那你丢掉了所有历史信息,因为你的本地只有当前版本以及部分历史信息。
假设GitHub服务器没了,你不会丢掉任何git历史信息,因为你的本地有完整的版本库信息。你可以把本地的git库重新上传到另外的git服务商。
二、git安装
git创建版本库
创建新版本库
(1)版本库又名仓库(repository),可以理解为一个目录,这个目录被git管理起来,每个文件的修改、删除、增加,git都能跟踪;
(2)创建版本库的第一步就是创建一个目录;
(3)第二步就是初始化git目录,git init
将这个目录变为git可以管理的目录;
克隆现有仓库
(1) git clone 命令,Git 克隆的是该 Git 仓库服务器上的几乎所有数据,而不是仅仅复制完成你的工作所需要文件;
(2)这会在当前目录下创建一个名为 help-docs 的目录,并在这个目录下初始化一个 .git 文件夹, 从远程仓库拉取下所有数据放入 .git 文件夹,然后从中读取最新版本的文件的拷贝;
git跟踪文件
(1)对于版本控制系统,只能管理文本文件,比如txt文件、程序代码、网页等,他可以告诉你每次的改动;
(2)版本控制系统,无法管理图片、视频等二进制文件,包括Microsoft的Word文件(二进制格式);
三、git状态
按照文件存放的位置区分
(1)workspace:工作区,就是你在电脑里能看到的目录,或者目前你正在编码的目录;
(2)Repository:版本库,就在.git目录;
(3)stage(index):暂存区,暂时管理文件的区域;
(4)Remote:远端仓库;
按照文件的状态区分
-
Untracked:新增文件,未被git追踪文件
-
Unmodified:未修改的文件,新增文件添加至暂存区或者已提交到本地仓库的文件
-
Modified:暂存区或者本地目录有修改的文件
-
Staged:暂存区的文件
git使用
git 提交文件
(1)当我们在git管理目录下建一个新文件,比如test.py,此时使用git status命令
查看文件所处的状态;
(2)可以看到新建的文件将处于Untracked files
状态,需要使用git add XXX命令
将文件添加到版本库的文件暂存区域(stage or index),此时文件状态将更新为stage;
(3)当我们修改test.py文件后,此时文件将处于modify状态,git会显示Changes not staged for commit(修改没有被添加至缓存区):
此时也需要使用git add XXX命令
将文件添加到暂存区域(stage or index);
(4)此时再看文件状态,git将提示Changes to be committed
,接下来可以使用git commit命令
将文件提交至本地仓库;
(5)当缓存区的内容都被commit之后,git状态将显示nothing to commit, working tree clean
,说明工作区内容已全被处理,是干净的状态;
(6)如果需要将本地仓库的内容提交到远程仓库,最后再使用git push XXX(文件名)命令
。
(7)用git diff HEAD -- XXX命令
可以查看工作区和版本库里面最新版本的区别
git撤销修改
以上都是对文件的提交操作,对于某些改动需要回退如下操作:
(1)对于新增加的文件,如果仍为untracked,可以直接删除(因为git对这个文件的存在不清楚);
(2)对于修改的文件,可以"git checkout -- <file>"
,重新checkout该文件,丢弃工作区的修改:
① 对于未放到暂存区的修改,将回到和版本库一样的状态;
② 对于已放到暂存区但又重新修改的文件,将回到暂存区的状态;
(3)如果被git add到暂存区,但没有做git commit提交
1)使用git reset将文件从索引区移除(但会保留在工作区)
git reset HEAD <file>
2)撤销工作区中文件a的修改
git checkout --<file>
(4)如果已被提交,则需要先回退已提交内容,然后撤销文件的修改
1)回退当前提交到工作区
git reset HEAD^
2)撤销工作区中文件a的修改
git checkout --<file>
(5)对于已经push到远程仓库的文件,可以使用git revert
回退修改。
(6)补充相关撤销内容:
# 移除缓存区的所有文件(i.e. 撤销上次git add)
$ git reset HEAD
# 将HEAD重置到上一次提交的版本,并将之后的修改标记为未添加到缓存区的修改
$ git reset <commit>
# 将HEAD重置到上一次提交的版本,并保留未提交的本地修改
$ git reset --keep <commit>
# 放弃工作目录下的所有修改
$ git reset --hard HEAD
# 将HEAD重置到指定的版本,并抛弃该版本之后的所有修改
$ git reset --hard <commit-hash>
# 用远端分支强制覆盖本地分支
$ git reset --hard <remote/branch> e.g., upstream/master, origin/my-feature
# 放弃某个文件的所有本地修改
$ git checkout HEAD <file>
git删除文件
删除添加.gitignore文件前错误提交的文件:
$ git rm -r --cached .
$ git add .
$ git commit -m "remove xyz file"
四、git分支管理
(1)git创建分支,并切换到该分支:
git checkout -b XXX
# 相当于
git branch XXX # 创建本地分支
git checkout XXX # 切换分支 or git switch -c XXX(新版本git新增命令)
git checkout -b dev -t origin/dev #创建分支并关联远程分支
(2)查看当前分支,以下命令会列出所有分支,当前分支前面会标一个*号:
git branch
(3)合并某个分支到当前分支
git merge XXX # 此时会使用Fast forward模式
git merge --no-ff XXX # 表示不使用Fast forward模式,会新建一个commit
(4)删除分支
git branch -d xxx #删除指定的分支
git branch -D <name> #强行删除指定分支,一般用于丢弃一个没有被合并过的分支
(5)合并冲突分支解决
当我们新创建一个分支dev1,修改readme.txt文件后,此时提交完成dev1分支;然后我们切换到master分支,同样修改readme.txt文件,此时提交完成master分支;需要将dev1分支合并到master分支时,git告诉merge confict,此时需要将readme.txt文件修改为自己需要的内容后,重新git add,git commit提交。
(6)查看分支合并图
git log --graph命令可以看到分支合并图
(7)暂存和恢复工作区修改的内容
git stash <file> # 暂存工作区内容
git stash list # 查看暂时保留的内容
git stash apply stash@{0} # 恢复保留的内容,但是恢复后,stash内容并不删除
git stash drop #删除stash的内容
git stash pop # 恢复的同时把stash内容也删
(8)在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick <commit>
命令,把bug提交的修改“复制”到当前分支,避免重复劳动。
(9)多人协作模式
-
首先,可以试图用git push origin 推送自己的修改;
-
如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
-
如果合并有冲突,则解决冲突,并在本地提交;
-
没有冲突或者解决掉冲突后,再用git push origin 推送就能成功!
如果git pull提示no tracking information,
则说明本地分支和远程分支的链接关系没有创建,
用命令git branch --set-upstream-to <branch-name> origin/<branch-name>