这结课是我收获最多也是最大的一门课了,从什么也不知道,步入了入门Git的过程。
Git的正确使用姿势
为什么要学习Git?
- 协同工作:因为绝大多数的公司都是基于Git进行代码管理,因此学会Git是每个程序员必备的技能。
- 开源社区:目前绝大多数的开源项目都是基于Git维护,参与这些项目开发都需要使用Git。
总结:工作需要Git,学不会Git在公司中无法进行业务操作。
本地版本控制 RCS
- 通过本地复制文件夹,来完成版本控制,通过不同的文件夹名称来区分版本
- 开发了一些版本控制软件,如RCS
- 只能在本地使用,无法团队协作。
集中版本控制 SVN
- 提供一个远端服务来保存文件,所有用户的提交都提交到该服务器中
- 学习简单易于操作。支持二进制文件,对大文件友好(因为二进制进行编译速度快)。
- 只有联网才能够进行保存使用,如果不联网无法进行提交
- 分支并不完善,项目团队开发时比较困难
- 如果服务端出错会导致很多版本丢失
分布式版本控制 Git
- 每个库都有完整的提交历史,可以直接在本地进行代码提交
- 每次提交记录的都是完整的文件快照(我的理解为整个代码分支结构)
- 通过Push等操作来完成和远端代码的同步
- 分布式开发,每个库都是完整的提交历史
- 分支管理功能强大,方便整个团队进行开发
- 校验机制比较完整,不容易出现代码丢失
- 相对于SVN更复杂,对于大文件的支持不是特别好
Git的基本使用方式(和linux一样,本身就是为linux服务)
Git命令(提醒不要在终端中使用ctrl+c或者ctrl+v)
-
配置
-
git config
- 不同级别的Git配置
- global 全局级别配置
- system 系统级别配置
- local 本地级别配置
- 每一个级别的配置可能会重复,但是低级别的配置会覆盖高级别的配置
-
git remote(本地和远端关联的信息)
git remote -v
查看remotegit remote add orgin_ssh git@github.com:git/git.git
git remote add origin_http https://github.com/git/git.git
- 同一个Orgin设置不同的Push和Fetch URL:
git remote add orgin git@github.com:git/git.git
git remote set-url --add --push orgin git@github.com:my_code/git.git
可以通过此命令将代码送到不同的仓库中去 - SSH Remote
- URL:git@github.com:git/git.git
- 免密配置
- SSH可以通过公私钥的机制,将生成的公钥存放在服务端,从而实现免密访问。
- 目前的四种Key类型:dsa、rsa、ecdsa、ed25519.默认是rsa,推荐使用ed25519
- 因为有时候windows不允许使用dsa、rsa的key,会导致你有了公私钥之后仍然无法拉代码
ssh-keygen -t ed25519 -C "your@qq.com"
密钥默认存在~/.ssh/id_ed25519.pub中全程回车即可
-
vim .git/config
直接进入文件,改文件内容- 常见的vim操作就不介绍了
dd删除整行
:q(不保存退出)
- 常见的vim操作就不介绍了
-
用户名配置
git config --global user.name " "
git config -- global user.email 1844@qq.com
-
instead of 配置
git config --global url.git@github.com:.insteadOf https://github.com//
改变协议
-
Git 命令别名配置
git config --global alias.cin "commit --amend --no-edit"
将"commit --amend --no-edit"命令改为cin这个命令
-
-
提交代码
-
git add
touch README.md
建立一个说明文档(工作区中)- 可以通过vim 写入内容进README.md中
git status
看一下效果git add README.md
从工作区中加入到暂存区中- 此时会在objects中新增文件
git cat-file -p 文件ID(通过tree .git查看)
查看提交文件的内容
-
git commit
-
通过
git commit -m "add README.md"
将文件提交到git目录里 -
此时Objects中会新加入两个文件,一个是存储你上传文件的目录树的文件(blob类型),另一个是存储一个commit信息,文件的作者.
-
通过
git log
获取当前版本代码,如果代码更替,查找该代码时会出现parent 代码(ID),此时就可以通过tree的新 ID 获取当前文档内容,通过parent ID获取上个版本文档内容 -
commit --amend
通过该命令可以修改最近的一次commit信息,修改后commit ID会改变,但是tree和Blob ID不会改变,这时会增加一个新的commit Object- 此时原来的commit 会变成一个悬空的Object,就是没有ref指向的Object,可以通过
git fsck --lost-found
来查找到处于悬空的Object
- 此时原来的commit 会变成一个悬空的Object,就是没有ref指向的Object,可以通过
-
rebase
-
filter --branch
该命令可以指定删除所有提交中的某个文件或者全局修改邮箱地址等操作
-
-
Git GC 删除某些无用的Object,并且对Object进行打包压缩减少仓库的体积
-
Reflog reflog 是用于记录操作日志的,防止误操之后数据丢失,可以通过reflog来找到丢失的数据,手动将日志设置为过期
git reflog expire --expire=now --all
和git gc --prune==now
cat .git/packed-refs
查找到打包后的commit ID
-
git gc prune=now 指定的是修剪多久之前的对象,默认是两周前
-
每一个commit都会有一个完整的版本,进行版本的管理
-
-
远端同步
- 拉取代码
- clone 拉取完整的仓库到本地目录,可以指定分支,深度
- pull 拉取远端某分支,并和本地代码进行合并,操作等同于
git fetch + git merge
也可以通过git pull --rebase
完成git fetch + git rebase
操作 - fetch 将远端某些分支最新代码拉取到本地,不会执行merge操作,会修改 refs/remote 内的分支信息,如果需要和本地代码合并需要手动操作
- 推送代码
- push 将本地代码同步到远端的方式
git push orgin master
即可完成同步
- 冲突问题,如果本地的commit记录和远端的commit历史不一致,则会产生冲突,比如
git commit --amend
修改commit ID 或者git rebase
都会出现这个问题 - 正常都要通过解决冲突之后再进行推送。
- push 将本地代码同步到远端的方式
- 拉取代码
Git基本命令:
ls (List directory contents)
用来显示目录或具体文件列表。类似于dir。mkdir
创建文件夹git init
初始化仓库,默认分支为master。git init --inital-branch
初始化分支并且命名为branchgit init --bare
创建一个裸仓库,纯git目录,不允许添加其他文件.git init --template
可以通过模板来创建预先构建好的自定义git目录.(没看懂)
tree .git
以树形结构列出(无tree命令需要进行下载)- head表示当前分支
- config当前配置
- object存储一些文件信息(四种Object)
- Blob存储文件内容
- Tree存储文件的目录信息
- Commit存储提交信息,对应当前Commit的版本代码
- 通过Commit可以看到TreeID,通过TreeID可以获得对应目录树的信息,通过该信息可以看到BlobID,通过BlobID可以看到该文件的内容
- tag 存储它真正指向的是其他ID,还有是谁储存了该标签,该标签的名字是什么,标签类型是什么
- refs存一些分支信息
-
经过实践可得,ref像一个指针,指向对应的commit来表示当前Ref对应的版本
-
ref中的tags是一个标签,你可以设置这个标签
git tag v0.0.1
这个标签中存储的也是当前Commit对应的ref对应的版本
-
git tag -a v0.0.2 -m "add feature 1"
创建辅助标签,此辅助标签中存储的ID和ref版本ID不同
-
git checkout -b test
创建一个新的分支test,然后再用cat .git/refs/heads/test
可以看到存储的内容和master内容相同,证明都是存储的commit当前版本信息的一个ID
Git仓库
- 工作区和暂存区
- 我们写代码或者改文件都在工作区进行
- 通过stage Fixes命令加入暂存区,然后通过commit 提交到目录中
Git研发流程
- 集中式工作流
- 只依托于master分支进行研发活动
- 工作方式
- 获取远端的master代码
- 直接在master分支完成修改
- 提交前拉取最新的master代码和本地代码进行合并(rebase),如果有冲突则需要解决冲突
- 提交本地代码到master
常见问题
-
为什么配置后Git,仍然无法进行代码拉取?
- 没有配置密钥
- 没有权限
- insteadOF没有进行配置(也就是说没有进行协议转换),比如你进行了SSH免密配置,但是用的是HTTP协议访问
-
为什么我Fetch了远端分支,但是我看本地当前的分支历史仍然没有变化?
- Fetch只会更新origin这个分支。
- fetch 只会将远端的代码拉取到本地的远端分支,但是并不会进行合并,因为为了避免发生冲突问题,需要进行merge进行合并
Fetch: git fetch从远程分支拉取代码,fetch常结合merge一起用.git fetch + git merge == git pull 一般要用git fetch+git merge,因为git pull会将代码直接合并,造成冲突等无法知道,fetch代码下来要git diff orgin/xx来看一下差异然后再合并。
总结:收获满满,所以记作笔记。