git使用(1)| 青训营笔记

69 阅读7分钟

Git的作用

  • 协同工作。业界绝大多数公司都是基于Git进行代码管理,因此Git是一个程序员的必备技能
  • 开源社区。目前绝大多数的开源项目都是基于Git维护的,参与这些项目的开发都需要使用Git。

Git是什么?

版本控制

版本控制一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统

    Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.

为什么需要版本控制?

  • 更好的关注变更,了解到每个版本的改动是什么,方便对改动的代码进行检查,预防事故发生;
  • 也能够随时切换到不同的版本,回滚误删误改的问题代码;

版本控制工具

版本控制类型代表性工具解决的问题基本原理优缺点
本地版本控制RCS本地代码的版本控制本地保存所有变更的补丁集,可以理解成就是所有的Diff,通过这些补丁,我们可以计算出每个版本的实际的文件内容只能本地使用,无法团队协作,使用场景有限
集中式版本控制SVN提供一个远端服务器来维护代码版本。本地不保存代码版本,解决多人协作问题提供一个远端服务来保存文件,所有用户的提交都提交到该服务器中,增量保存每次提交的Diff,如果提交的增量中和远端现存的文件存在冲突,则需要本地提前解决冲突学习简单,支持二进制文件,对大文件支持更友好;本地不存储版本管理的概念,所有提交都只能联上服务器后才可以提交,分支上的支持不够好,对于大型项目团队合作比较困难,用户本地不保存所有版本的代码,如果服务端故障容易导致历史版本的丢失
分布式版本控制Git每个仓库都能记录版本历史,解决只有一个服务器保存版本的问题每个库都存有完整的提交历史,可以直接在本地进行代码提交;每次提交记录的都是完整的文件快照,而不是记录增量;通过Push等操作来完成和远端代码的同步分布式开发,每个库都是完整的提交历史,支持本地提交,强调个体;分支管理功能强大,方便团队合作,多人协同开发;校验和机制保证完整性,一般只添加数据,很少执行别除操作,不容易导致代码丢失。 相对SVN更复杂,学习成本更高;对于大文件的支持不是特别好(git-lfs工具可以弥补这个功能)

Git基本命令

image.png

Git介绍

git init
mkdir dirname
cd dirname
git init

在执行完成 git init命令后,Git 仓库会生成一个 .git 目录,默认为master分支。该目录包含了资源的所有元数据,其他的项目目录保持不变。git init其他参数:

  • --initial-branch:初始化的分支
  • --bare:创建一个裸仓库(纯Git目录,没有工作目录)
  • --template:可以通过模板来创建预先构建好的自定义git目录
git config

用户名配置

git config --global user.name "username"
git config --global user.email xxx@xxx.com

Instead of 配置:

git config --global url.git@github.com:.insteadOf https://github.com/

Git命令别名配置

git config --global alias.cin "commit --amend --no-edit"
git remote

查看远程仓库

git remote -v 

添加远程库

git remote add [origin] [url]

同一个Origin设置不同的Push和Fetch URL

git remote add origin [url1]
git remote set-url --add --push origin [url2]
HTTP Remote

免密配置

URL形式:github.com/git/git.git

内存:git config --global credential.helper 'cache--timeout:=3600'

硬盘:git config --global credential.helper "store --file/path/to/credential-file" 不指定目录的情况默认是~/.git-credentials

SSH Remote

URL形式:git@github.com:git/git.git

免密配置

SSH可以通过公私钥的机制,将生成公钥存放在服务端,从而实现免密访问。

目前的Key的类型四种,分别是dsa、rsa、ecdsa、ed25519。默认使用的是rsa,由于一些安全问题,现在已经不推荐使用dsa和rSa了, 优先推荐使用ed25519

生成公密钥:

ssh-keygen -t ed25519 -C [email]
git add

git add命令后文件会被添加到暂存区

git add [path]
git commit

git commit将暂存区的文件提交到仓库

git commit -m "[description]"
.git下的objects
  • Blob:存储文件的内容
  • Tree:存储文件的目录信息,可以多个Blob信息
  • Commit:存储提交信息:一个Commit可以对应唯一版本的代码

如何把三个Object信息串联在一起?

  1. 通过Commit寻找到Tree信息,每个Commit都会存储对应的Tree ID
  2. 通过Tree存储的信息,获取到对应的目录树信息
  3. 从tree中获得blob的ID,通过Blob ID获取对应的文件内容
.git下的refs

Refs文件存储的内容对应Commit ID,可以把ref当做指针,指向对应的Commit来表示当前Ref对应的版本。

refs/heads前缀表示的是分支,除此之外还有其他种类的ref,比如refs/tags前缀表示的是标签。

image.png

分支管理-branch

创建分支命令:

git branch (branchname)

切换分支命令:

git checkout (branchname)

创建并切换到新分支

git checkout -b (branchname)
git tag

表示发布稳定版本

git tag v0.1
Annotation Tag——附注标签

附注标签是一种特殊的标签,可以为tag增加一些信息

git tag -a v0.1 -m "标签信息"
追溯历史版本

上面提到Refs中指向得问Commit可以获取唯一的代码版本。Commit中存有parent commit字段,通过commit的串联获取历史版本的代码。

commit --amend:可以修改最近的一次commit信息,修改之后commit id会变。

rebase:通过git rebase -i HEAD~3可以实现对最近三个commit的修改:1、合并commit;2、修改具体的commit message;3、删除某个commit

filter --branch:可以指定删除所有提交中某个文件或者全局修改邮箱地址等操作。

悬空Object:没有ref指向的object,通过fsck查看

git fsck --lost-found
Git GC

git gc可以删除一些不需要的object,以及会对object进行打包压缩来减小仓库的体积.

git gc --prune=now

git reflog:reflog是用于记录操作日志,防止误操作后数据丢失,通过reflog来找到丢失的数据,手动将日志设置为过期。

git reflog expire --expire=now --all
git clone & pull & fetch
  • Clone:拉取完整的仓库到本地目录,可以指定分支,深度。
  • Fetch:将远端某些分支最新代码拉取到本地,不会执行merge操作,会修改refs/remote内的分支信息,如果需要和本地代码合并需要手动操作。
  • Pull:拉取远端某分支,并和本地代码进行合并,操作等同于git fetch + git merge也可以通过git pull -rebase完成git fetch + git rebase操作。可能存在冲突,需要解决冲突。
git push

push:将本地代码同步到远端。git push origin master

冲突问题

  1. 如果本地的commit记录和远端的commit历史不一致,则会产生冲突,比如git commit --amend or git rebase都有可能导致这个问题.
  2. 如果该分支就自己一个人使用,或者团队内确认过可以修改历史则可以通过git push origin master -f来完成强制推送,一般不推荐主干分支进行该操作,正常都应该解决冲突后再进行推送。

推送规则限制

可以通过保护分支,来配置一些保护规则,防止误操作,或者一些不合规的操作出现,导致代码丢失。