Git
参考文献
哈希
哈希是一个系列的加密算法,各个不同的哈希算法虽然加密强度不同,但是有以下几个共同点:
①不管输入数据的数据量有多大,使用同一个哈希算法,得到的加密结果长度固定
②哈希算法确定,输入数据确定,输出结果保证不变
③哈希算法确定,输入数据有变化,输出结果一定有变化,而且通常变化很大
④哈希算法不可逆
⑤哈希算法中不区分英文大小写
哈希算法有很多种,如:MD5、SHA-1等.Git 底层采用的是 SHA-1 ,因为哈希算法可以被用来验证文件,Git 就是靠这种机制来从根本上保证数据完整性的
Git特点
直接记录快照,而并非差异比较
Git把数据看作是对小型文件系统的一组快照,每次提交更新或Git中保存项目状态时,Git主要对当时的全部文件制作一个快照并保存这个快照的索引 .为了高效,如果文件没有修改,Git不再重新存储改文件,而是只保留一个链接指向之前存储的文件,Git对待数据更像一个快照流 .
Git中文件的三种状态
已暂存(staged) : 表示对一个已修改的文件的当前版本做了标记,使之包含在下次提交的快照中.
已修改(modified) : 表示修改了文件,但还没有保存到数据库中;
已提交(committed) : 表示数据已经安全的保存在本地数据库中;
Git 三个区域
工作目录(Working tree) : 是对项目的某个版本独立提取出来的内容;
暂存区(staging area) : 是一个文件,保存了下次提交的文件信息,一般在Git仓库目录中.
Git仓库(Git directory) : Git用来保存项目的元数据和对象数据库的地方,这是Git中最重要的部分,从其他计算机克隆仓库时,拷贝的就是这里的数据.
基本工作流程:
Git操作流程图
Git命令
初步配置
git config
可以配置Git外观和行为的配置变量,这些变量存储在三个不同的位置
/etc/gitconfig
文件: 系统级 使用--system
设置
~/.gitconfig
或~/.config/git/config
: 只针对用户 ,使用--global
设置
当前使用仓库的Git目录中的config
文件(就是.git/config
): 针对仓库 ,使用该--local
选项强制 Git 读取和写入此文件
Tips: 低级别的配置会覆盖高级别的配置 ,即.git/config
配置的变量会覆盖/etc/gitconfig
中的配置信息
用户信息
1 2 git config --global user.name "用户名" git config --global user.email "邮箱"
若使用了--global
选项,那么该命令只需要运行一次,因为之后无论在系统上做任何事,Git都会使用这些配置信息.
若想对针对特定项目使用不同的用户名称与邮箱,可以在那个项目目录中配置用户信息时,不使用--global
选项
检查配置信息
1 2 3 4 5 6 7 git config --list git config <key> git config --show-origin <key>
获取帮助信息
1 2 3 git help <command > git <command > --help man git-<command >
初始化仓库
克隆已有仓库
1 2 3 4 5 6 git clone <url> git clone -c http.proxy="http://127.0.0.1:1087" https://github.com/ git config --global http.https://github.com.proxy socks5://127.0.0.1:1086
操作文件
检查文件状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 git status git status -s /git status --short M README MM Rakefile A lib/git.rb M lib/simplegit.rb ?? LICENSE.txt
跟踪新文件(添加内容到下次提交中)
1 2 3 4 git add <file> git add .
可以用来开始跟踪新文件
把已跟踪的文件放到暂存区
用于合并是把有冲突的文件标记为已解决状态等
git add --patch
命令
中文说明
y
暂存此块变更
n
不暂存此块变更
q
退出,不暂存此块变更或其他块
a
暂存此块变更,并暂存后续所有块
d
不暂存此块变更,也不暂存后续块
g
选择要跳转的块
/
使用正则表达式搜索块
j
保持此块未决定,查看下一个块
J
保持此块未决定,查看下一个块
k
保持此块未决定,查看上一个块
K
保持此块未决定,查看上一个块
s
将当前块拆分为更小的块
e
手动编辑当前块
?
显示命令列表
若在add
时错误添加可以在git reset -p
来取消暂存的hunk
忽略文件
处理无需纳入git管理的文件,文件后缀名为.gitignore
.gitignore
文件的模式规则如下:
模板
Tips:在简单的情况下,存储库.gitignore
的根目录中可能只有一个文件,该文件递归地应用于整个存储库.但是,也可以.gitignore
在子目录中包含其他文件.这些嵌套.gitignore
文件中的规则仅适用于它们所在目录下的文件.Linux 内核源代码库有 206 个.gitignore
文件.
对比已暂存和未暂存的更改
1 2 3 4 git diff git diff --staged / git diff --cached
需要注意的是,git diff
本身并不显示自上次提交以来所做的所有更改 — 仅显示尚未暂存的更改. 如果您已暂存所有更改,则 git diff
不会给您任何输出.
1 2 3 4 5 git diff => 工作目录 vs 索引 git diff HEAD => 工作目录 vs HEAD git diff --cached HEAD => 索引 vs HEAD git diff --cached => 索引 vs HEAD git diff HEAD^ HEAD => HEAD^ vs HEAD
提交更新
1 2 3 4 5 6 7 8 9 git commit -m "提交的信息" git commit -a -m "提交的信息" git commit --amend -m [message] git commit --amend [file1] [file2] ...
**提交时记录的是放在暂存区的快照.**任何还未暂存的任然保持已修改状态,可以在下次提交时纳入版本管理.每次运行提交操作,都是对项目做一次快照,以后可以回到这个状态,或者进行比较.
移除文件
1 2 3 4 5 6 7 git rm <file> git rm -f <file> git rm --cached <file>
从git中移除某个文件,就必须要从已跟踪文件清单移除(即从暂存区移除),然后提交
移动文件
1 2 3 4 5 git mv file_from file_to
查看提交历史
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 git log git log -P -2 git log --stat git log --pretty=oneline git log -S function_name git log --follow [file] git whatchanged [file] git log -p [file] git log -5 --pretty --oneline git shortlog -sn git log --pretty=format:"%h - %an, %ar : %s" git log --pretty=format:"%h %s" --graph
说明符
输出说明
%H
提交哈希
%h
缩写提交哈希
%T
树哈希
%t
缩写树哈希
%P
父哈希
%p
缩写的父哈希
%an
作者姓名
%ae
作者邮箱
%ad
作者日期(格式尊重 --date=option)
%ar
作者日期,亲属
%cn
提交者名称
%ce
提交者电子邮件
%cd
提交日期
%cr
提交日期,相对
%s
主题
选项
描述
-p
显示每次提交引入的补丁.
--stat
显示每次提交中修改的文件的统计信息.
--shortstat
仅显示来自 --stat 命令的更改/插入/删除行.
--name-only
显示提交信息后修改的文件列表.
--name-status
显示受添加/修改/删除信息影响的文件列表.
--abbrev-commit
仅显示 SHA-1 校验和的前几个字符,而不是全部 40 个字符.
--relative-date
以相对格式(例如,“2 周前”)而不是使用完整日期格式显示日期.
--graph
在日志输出旁边显示分支和合并历史的 ASCII 图形.
--pretty
以替代格式显示提交.选项值包括 oneline、short、full、fuller 和 format(在其中指定您自己的格式).
--oneline
--pretty=oneline --abbrev-commit
一起使用的简写.
限制日志输出
1 2 3 4 5 6 7 8 9 10 11 git log --since=2.weeks git log --author "xxx" git log --grep "xxx" git log -- path/to/file git log --pretty="%h - %s" --author='xxx' --since="2021-06-01" --before="2021-07-01" --no-merges --
tips: 若要得到同事满足这两个选项搜索条件的提交,就必须用--all-match
选项,否则满足任意一个条件的提交都会被匹配;
选项
描述
-<n>
只显示最近的 n 次提交
--since
, --after
将提交限制为在指定日期之后进行的提交.
--until
, --before
将提交限制为在指定日期之前进行的提交.
--author
仅显示作者条目与指定字符串匹配的提交.
--committer
仅显示提交者条目与指定字符串匹配的提交.
--grep
只显示带有包含字符串的提交消息的提交
-S
只显示提交添加或删除匹配字符串的代码
撤销
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 git checkout [file] git checkout [commit] [file] git checkout . git reset [file] git reset HEAD <file> git reset --hard git reset [commit] git reset --hard [commit] git reset --keep [commit] git restore --staged <file> git restore <file> git revert [commit] git stash git stash pop
操作远程仓库
查看远程仓库
1 2 3 4 5 git remote git remote -v
添加远程仓库
1 2 3 4 git remote add <shortname> <url> git remote add pb https://github.com/paulboone/ticgit
从远程仓库拉取
推送到远程仓库
1 2 git push <remote-name> <branch-name>
Tips: 只有有所克隆服务器的写入权限,并且之前没有人推送是,这条命令才能生效.
当你和其他人在同一时间克隆,他们先推送到上游后,你再推送到上游,你的推送将会被拒绝,必须先将他们的工作拉取下来并合并进你的工作目录后才能推送
故在每次推送之前建议先拉取一下最新的代码,若存在冲突,先解决冲突后在进行提交,操作如下:
查看某个远程仓库
1 git remote show <remote-name>
修改远程仓库地址
1 2 3 4 5 6 git remote set-url <remote-name> <url> git remote rm <remote-name> git remote add <remote-name> <url>
远程仓库的移除与重命名
1 2 3 git remote rename <new-name> git remote rm <remote-name>
标签
Git可以给历史中某一个提交打上一个标签,以示重要性.
列出标签
查找标签
创建标签
1 2 3 4 5 6 7 git tag -a <tag-name> -m <tag-description> git tag -a <tag-name> git tag -a <tag-name> -m <tag-description> commit_hash
推送标签到远程仓库
1 2 3 4 git push remote <tag-name> git push remote --tags
删除标签
1 2 3 4 5 6 7 8 9 10 git tag -d <tag-name> git push origin :refs/tags/<tag-name> git push origin :refs/tags/transaction remote: Powered by GITEE.COM [GNK-6.3] To https://gitee.com/HoleLin/MyBlog.git - [deleted] transaction
分支操作
基础操作
1 2 3 4 5 6 7 8 9 git branch <branch-name> git checkout <branch-name> git branch -d <branch-name>
合并分支
需要检出到你想要合并如的分支,然后执行git merge
命令
远程分支
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 git ls-remote <remote-name> git ls-remote origin 8e2d1c4205103fd5da8808d3aa1c62ec11276e70 HEAD 8e2d1c4205103fd5da8808d3aa1c62ec11276e70 refs/heads/main 5dcf443915f4f809c92db0425449251afb149088 refs/heads/master git remote show <remote-name> git remote show github-main origin git remote show origin * remote origin Fetch URL: https://gitee.com/xxxx/xxxx.git Push URL: https://gitee.com/xxxx/xxxx.git HEAD branch: main Remote branches: main tracked master tracked Local branch configured for 'git pull' : main merges with remote main Local ref configured for 'git push' : main pushes to main (up to date ) git push origin --delete <barnch-name>
推送
基础操作
1 2 3 4 5 git push origin serverfix:serverfix git push origin serverfix:awesome-branch
变基-rebase
变基操作实质是丢弃一些现有提交,然后相应地新建一些内容一样但实际上不同的提交.
Patch
什么是patch?简单来讲,patch中存储的是你对代码的修改
什么是生成patch?生成patch就是记录你对代码的修改并将其保存在patch文件中
什么是打patch?打patch就是将patch文件中对代码的修改,应用到源代码,从而把对代码的修改应用到code中.
使用git的format-patch和am命令进行生成patch和打patch,用此方法获得的patch其实就是commit里提交的code修改以及commit信息
对于git这种以project为单位的修改,尤其是涉及到多个文件夹下的多个文件的改动时,非常方便,能够记录所有的改动(添加,修改,删除文件等)
可以保存commit信息.
能够灵活的获取patch.可以获取任意两个commit之间的patch集.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 $ git format-patch HEAD^ $ git format-patch HEAD^^ $ git format-patch HEAD^^^ $ git format-patch HEAD^^^^ $ git format-patch <r1>..<r2> $ git format-patch -1 <r1> $ git format-patch <r1> $ git format-patch --root <r1> $ git format-patch -M master $ git format-patch –n 07fe --n指patch数,07fe对应提交的名称
git am
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ git apply --stat 0001-limit-log-function.patch $ git apply --check 0001-limit-log-function.patch $ git am 0001-limit-log-function.patch $ git am --signoff 0001-limit-log-function.patch $ git am ~/patch-set/*.patch $ git am --abort $ git am --resolved
git pull
和git fetch
的区别
git pull
是一个便捷命令,它可以从远程仓库拉取代码,并自动合并到当前分支.它实际上包含了两个步骤:先执行git fetch
,然后执行git merge
.如果远程仓库有新的提交,git pull
会将这些提交下载到本地,并尝试将其合并到当前分支.
git fetch
也用于从远程仓库拉取代码,但不会自动合并到当前分支.它只是将远程仓库最新的代码下载到本地,并更新本地的远程分支指针.你可以使用git merge
或git rebase
命令手动将最新的代码合并到当前分支.
总结起来,git pull
是git fetch
和git merge
两个步骤的组合,而git fetch
只是简单地获取远程仓库的最新代码到本地,并不进行合并操作.在多人协作的项目中,推荐使用git fetch来获取最新代码,然后再根据需要选择合并方式(merge
或rebase
)进行代码更新.
遇到问题
服务器上进行git pull
时一直提示需要输入密码
1 2 3 4 git config --global credential.helper store git pull
第一命令设置凭证并将凭证存储到硬盘上
第二条命令执行后,输入账号密码后,会默认会在当前用户目录下生成git-credentials
,具体路径为:~/.git-credentials
git-credentials
文件中就存储了刚刚输入的账号密码,之后更新git
则会自动完成这个操作.