Git

167 阅读10分钟

git 概念

说明:以下命令中 <> 表示必传参数,[] 表示非必传参数

git 四个工作区域

git工作区域.png

  • workspace 工作区,存放代码的地方
  • index/stage 暂存区,临时存放的改动
  • repository 本地仓库,安全存放数据的位置,其中HEAD指向当前的分支,默认分支master,分支指向最新的版本(提交记录)
  • remote 远程仓库,托管代码的服务器

git工作区详情.png

git 文件的三种状态

  • modified 已修改
  • staged/indexed 已暂存
  • committed 已提交

命令行 vi 编辑文件

  1. vi <file> 进入文件
  2. 输入i 进入编辑状态
  3. 按下 Esc 结束编辑,重新进入命令行
  4. 输入 :wq 回车,写入并退出

git 配置

查询配置信息

  • git config --list 列出当前配置
  • git config --local --list 列出当前所在项目的配置
  • git config --global --list 列出全局配置
  • git config --system --list 列出系统配置 (很少用)

配置用户信息

git config --global user.name "my name"
git config --global user.email "my email"

删除变量

git config --global --unset user.email

.gitignore 忽略文件

# 忽略所有 .a结尾的文件
*.a
# 但 lib.a除外
!lib.a

# 忽略根目录下的 TODO 文件
/TODO

# 忽略build/目录下的所有文件
build/

# 忽略 doc/notes.txt 但不包括 doc/sub/notes.text
doc/*.txt

# 忽略doc/目录下的所有txt文件
doc/**/*.txt

git 版本

git --version

SSH

执行ssh-keygenusr/.ssh目录中生成

  • id_rsa.pub 公钥,将公钥内容复制到远程仓库的个人账号中
  • id_rsa 私钥

1. 工作区命令

1.1 新建仓库

  • git init 为当前文件夹进行git管理,创建一个新的本地仓库
  • git clone <url> [dir]url上克隆项目,dir默认是项目名

1.2 添加到暂存区

git add的三个作用:

  1. 将未追踪的文件加入到追踪列表中,如新建了一个文件,git并没有追踪到该文件,通过git add将该文件添加到暂存区,使git能追踪开始追踪该文件
  2. 将已追踪的文件并且修改了的文件,纳入到暂存区
  3. 文件出现冲突,解决冲突,通过git add把这个文件标识已解决冲突
  • git add . 将工作区所有已修改的文件添加到暂存区
  • git add <file...> 将工作区指定文件添加到暂存区
  • git add [dir] 将工作区只当文件夹包括所有文件添加到暂存区

1.2 撤销

  • git rm <file...> 删除工作区文件,并添加到暂存区,相当于执行了 rm <file...>, git add <file...>
  • git checkout -- <file...> 丢弃工作区中已修改的文件(丢弃掉相当于暂存区中最后一次添加文件内容所作的变更

2. 暂存区命令

2.1 恢复

  • git rm --cached <file...> 从暂存区中删除文件,工作区还有该文件
  • git reset HEAD <file...> 从暂存区中移除文件到工作区,对已经执行git add的文件恢复回去

2.2 版本回退

  • git reset --hard HEAD^ 回退前1个版本,^的数量代表前几个版本
  • git reset --hard HEAD~n 回退前n个版本
  • git reset --hard HEAD commit-id 回退到commit-id对应的版本,当不知道commit-id的时候,可以通过git reflog来查看操作记录对应的commit-id

2.2 提交

commit-id 摘要值,(sha1)计算,由于git是分布式管理的,能多个人同时运作,所以需要唯一值来管理,当执行 git commitgit会创建一个commit对象,并且将这个commit对象parent指针设置为HEAD所指向的引用sha1

  • git commit -m 'msg' 提交,每次提交都要声明内容
  • git commit --amend -m '修正的消息' 与前面提交的commit将会合成一条
  • git commit -am 'msg' 添加到暂存区并提交,git addgit commit 组合

    注意: 如果文件是新增的,版本库里面本身就没有该文件,git commit -am 将无效,需要拆分出来使用

2.3 stash 保存现场

应用场景,比如在 feature1开发功能,但是还没开发调试完毕;这个时候要切换dev去修复问题,无法直接切换分支过去,那么需要把当前的内容进行一个保存,等后续开发完毕,再拿出来继续修改

  • git stash [save 'msg'] 保存现场,的方式,先进后出
  • git stash list 查看保存的现场记录,会有索引值
  • git stash pop 应用最近的一条现场记录,并从stash中删除该记录
  • git stash apply [stash@{0}] 应用指定的一条现场记录,默认最近一条,但不会从statsh中删除该记录,需要手动执行 git stash drop [stash@{0}]进行删除

3. 本地仓库命令

3.1 添加远程仓库

  1. git remote add origin <remote-url> 本地仓库添加远程仓库地址
  2. git push -u origin master 将本地仓库和远程仓库的master分支关联,并推送到远程仓库
  3. git remote show origin 显示远程仓库信息

3.2 推送

  • git push 把本地仓库代码推送到远程仓库
  • git push [origin] [[src-branch]:[dest-branch]] push的完整写法,src-branch表示本地要推送的分支,默认当前所在的分支;dest-branch 表示远程分支,默认与本地分支同名;如develop对应origin/develop => git push origin develop:develop

3.3 拉取

  • git fetch 绝对能成功,只是从远程仓库拉取到本地仓库
  • git pull 从远程仓库拉取代码到本地仓库,同时会合并当前所在的分支与远程分支(git fetch + git merge组合)
  • git pull [origin] [[src-branch]:[dest-branch]] pull的完整写法,src-branch表示要拉取的远程分支,默认当前所在的分支对应的远程分支;dest-branch表示原地要合并的分支,默认和远程分支对应的本地分支 => git pull origin develop:develop

HEAD标记

  • HEAD文件是一个指向当前所在分支的引用标识符,该文件内部不包含sha1值,而是一个指向另外一个引用的指针ref
  • ORIG_HEAD 保存着 sha1-commitid
  • FETCH_HEAD 保存着 sha1-commitid msg

4. 其他

4.1 日志

  • git log [-n] 查看最近的n条提交记录
  • git log --pretty=oneline 一行显示一条记录
  • git log --graph 以图形化的方式查看log,常用于查看分支的分叉情况
  • git reflog 操作日志,区别于git log记录的是提交记录日志
  • git log origin/master 查看远程仓库日志,以下两个为完整写法
    • git log remotes/origin/master
    • git log refs/remotes/origin/master

5. branch 分支

5.1 创建分支

  • git branch <branch-name> 在当前所在的分支上创建一条新的分支
  • git branch [-a] 查看本地分支,-a表示查看所有分支,包括远程分支

5.2 切换分支

  • git checkout <branch-name> 切换到分支
  • git checkout - 切换到上一个所在的分支
    #有两个分支 master 和 dev
    # HEAD 在 master, 现在切换到dev
    git checkout dev
    # HEAD指向了 dev,现在切回master
    git checkout -
    # HEAD指向了master,再切回dev
    git checkout -
    
  • git checkout -b <branch-name> 创建一个分支,并切换到该分支(git branchgit checkout的组合)

5.3 删除分支

注意:如果删除的分支正好是当前所在的分支,将无法删除

  • git branch -d <branch-name> 删除分支,如果要删除的分支存在变化,且没有合并,将无法删除
  • git branch -D <branch-name> 直接删除分支,不管是否存在变化

5.4 合并分支

  • git merge <branch-name> 将指定的分支合并到当前所在的分支

5.5 图解分支操作

一、默认一个master分支

image.png

二、在master分支上创建dev分支,并切换到dev分支

git checkout -b dev

image.png

三、dev分支添加一个版本提交记录

git commit -m 'dev branch add new commit'

image.png

四、切换到master,把dev合并到master

git checkout master
git merge dev

image.png

5.6 Fast-Forward 快进模式

  • 如果可能,合并分支git会使用Fast-Forward模式
  • 删除分支的时候会丢弃分支信息
  • 合并分支加上--no-ff将禁用Fast-Forward,这样将多出一个commit-id

合并FF模式 git merge dev

image.png

禁用FF模式 git merge --no-ff dev,合并之后将多出一个提交记录

image.png

5.7 git分支模型

  • develop 频繁变化的分支,常用于开发,由feature/xxx某个功能的分支开发完毕合并过来
  • test 供测试与产品等人用的,不频繁变化,develop分支开发完毕的功能将合并到该分支,由测试人员发布并进行测试
  • release 预发布版本,用于公测版,内测完毕后合并到该分支
  • master 主分支,变化很少,用于生产,一般两周会有版本迭代,公测完毕后合并到该分支
  • bugfix/hotfix 生产中出现紧急bug,从master拉取分支用于修复

5.8 推送和拉取分支

  1. 本地有develop分支,远程没有develop分支,在本地develop去push将失败,因为没有对应的远程分支,执行git push --set-upstream origin develop将本地的develop分支推送到远程,并且在远程创建一个develop分支与之对应
  2. 远程有develop分支,执行git pull拿到本地的是
    master
    remotes/origin/master
    remotes/origin/develop
    
    本地没有develop分支,执行
    • git checkout -b develop origin/develop
    • git checkout --track origin/develop 在本地创建一个分支develop,并与origin/deveop对应

5.9 删除远程分支

  • git push origin --delete develop 删除远程的develop分支
  • git push origin :develop 旧的方式,推送一个空的分支到远程的develop分支,将删除远程develop分支

5.10 重命名远程分支

先删除远程分支,再推送一个新的分支名

5.11 refspec

本地分支与远程分支的对应关系,本地tag和远程tag的对应关系

在缺省情况下,refspec会被git remote add命令所自动生成,git会获取远程上refs/heads下的所有引用,并将它们写入到本地的refs/remotes/origin目录下,所以,如果远程上有一个master分支,我们本地旧可以通过下面几种方式来访问他们的历史记录

  • git log origin/master
  • git log remotes/origin/master
  • git log refs/remotes/origin/master

6. tag 标签管理

版本管理 NNN.nnn.mmm, 历史上的一个快照(静态),只是增加一个指针而已,与branch无关联,tagcommit没什么大的区别,只是比sha1更容易识别

  • N 大版本号 (全面改动较大的时候)
  • n 小版本号 (新功能)
  • m bug修正版本
  • git tag v1.0.0 轻量级标签,只是生成一个指针指向commit-id
  • git tag -a v2.0.0 -m 'release version' 重量级标签,带注释,生成一个tag对象,有自己的id,还有一个指针指向commit-id
  • git tag -d tag-name 删除标签
  • git tag 查看标签
  • git tag -l 'v1.0.0' 查看v1.0.0标签
  • git tag -l '*2' 查找2结尾的标签
  • git tag -l 'v*' 查找v开头的标签

6.1 推送tag到远程

  • git push origin <tag...> 将指定tag推送到远程仓库
  • git push origin refs/tags/v1.0:refs/tags/v1.0 完整命令,:左边为本地tag,右边为远程tag
  • git push origin --tags 将本地所有未推送的tag全部推送到远程仓库

6.2 拉取tag到本地

  • git pull 拉取远程所有内容
  • git fetch origin tag v1.0.0 将远程v1.0.0的tag拉取到本地

6.3 删除远程tag

  • git push origin --delete tag v1.0 删除远程v1.0的tag
  • git push origin :refs/tags/v1.0 推送一个空的tag到远程v1.0的tag,将删除远程的tag v1.0 删除了远程tag或者本地tag,只删除一个,另一个仓库始终不用同步删除,都需要手动删除

7. diff 差异

  • git diff 比较暂存区工作区的差异,左边暂存区源(--),右边工作区目标(++)
  • git diff HEAD 比较最新的提交工作区的差异
  • git diff --cached [commit-id] 比较最新的提交暂存区的差异

7.1 文件冲突

<<<<<<<<< HEAD # 本地仓库改的内容
xxxxx
======
xxxxx
>>>>>>>> 1038as7d89ahhd 其他仓库修改的内容

8. 应用场景

8.1 撤销文件的修改

  1. 工作区添加一个文件 test.html, 添加到暂存区git add test.html,提交一个版本 git commit -m 'add new file'
  2. 删除 test.html, 添加到暂存区 git add test.html
  3. 恢复test.html,从暂存区中恢复到工作区git reset HEAD -- test.html
  4. 将工作区中的修改丢弃 git checkout -- test.html,恢复 test.html