前语
本文首要讲Git
的相关常识,特别是关于rebase、revert指令的一些个人了解,欢迎我们纠正。articles/2023-03-14-GIt韶光机(简单小例子).md at main slshsl/articles (github.com)
Git 与其他版别控制体系的差异
Git
直接记录快照,而非差异比较。
Git 完整性
Git
中一切的数据在存储前都核算校验和,然后以校验和来引证。Git
用以核算校验和的机制叫做 SHA-1 散列(hash
,哈希)。
Git 怎样存储数据
Git存储数据有点像 key-value store
,key
能够以为是data
的sha1
哈希,value
以为是数据本身。
value是经过ZLib紧缩过的
Git 根底概念
Working Space / Working Directory
: 作业区/作业目录,便是你平时存放项目代码的地方,本文一致运用作业区
Index / Stage
: 暂存区/索引区,用于暂时存放你的改动,本文一致运用暂存区
Local Repository
: 本地库房(本地版别库)本文一致运用本地库房
Stash
:储藏区
Remote Repository
: 长途库房(长途版别库)本文一致运用长途库房
<remote_name>/<branch_name>
:本地长途分支引证/本地长途盯梢分支,本文一致运用本地长途盯梢分支
常用指令
git xxx -h
检查某个指令的帮助信息。
git config
# 检查git装备
$ git config -l`
# 检查体系装备
$ git config --system --list
# 检查用户装备
$ git config --global --list
# 检查项目装备
$ git config --local --list
# 设置用户称号
$ git config --global user.name xxx
# 设置用户邮箱
$ git config --global user.email xxx
# 启动的编辑器一般为 vim。 当然也能够指令设置你喜欢的编辑器。
# 我一般习惯设置成vscode
$ git config --global core.editor xxx
# 项目启用rerere
$ git config rerere.enabled true
# 设置log -1 HEAD的别名为last
$ git config --global alias.last 'log -1 HEAD'
# 运用last别名
$ git last
每一个等级会掩盖上一等级的装备
git init
初始化一个库房。
git clone
# 克隆一个库房
$ git clone <url>
git clone
指令做了什么?
- 增加一个盯梢的长途库房
remote
,主动将其命名为origin
,拉取它的一切数据 - 创立一个
origin/master
(本地长途盯梢分支) - 创立一个
master
(本地分支)
# 克隆一个库房
$ git clone —depth=1 <url>
一般我们直接运用 git clone
即可克隆项目,假定仅仅运用一个库房项目,这是参加–depth=1参数能够使我们只下载当时的最新提交即可。
git add
增加作业区的内容至索引区。
git status
显现当时的状况。
$ git status
On branch dev
Your branch is ahead of 'origin/dev' by 2 commits.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: a.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: a.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
c.txt
- 显现当时分支与其本地长途盯梢分支(假定有)的关系
能够经过
git push
推到长途的commit - 显现暂存区和本地库房有差异的文件
经过运转
git commit
会增加到本地库房的文件 - 显现作业区和暂存区有差异的文件
经过运转
git add
能够增加到暂存区的文件 - 显现作业区中不被
git
追寻的文件(也不被.gitignore
忽略) 经过运转git add
能够增加到暂存区的文件
git commit
# 提交变更到本地库房
$ git commit -m "xxx"
# 修补提交:修补终究的提交
$ git commit --amend
# 修补提交:修补终究的提交,不修正提交信息
$ git commit --amend --no-edit
git commit --amend
:修补终究的提交时,是彻底用一个新的提交替换旧的提交。修补提交最明显的价值是能够略微改进你终究的提交,例如一些小的修补,笔误等等;能够像下面这样操作:
# 第一次提交
$ git commit -m 'initial commit'
# 修正笔误等
$ git add forgotten_file
# 第2次提交
$ git commit --amend
终究你只会有一个提交;第2次提交将代替第一次提交的结果。
假定你的代码现已
push
了的话,git commit --amend
要慎用,因为会修正提交前史。
# 带签名的提交
git commit --signoff -m 'xxxx'
git log
# 基本用法
$ git log
# 仅显现最近的 n 条提交
$ git log -<n>
# 按补丁格局显现每个提交引入的差异
$ git log -p
# 显现每次提交的文件修正计算信息
$ git log --stat
# 在日志旁以 ASCII 图形显现分支与兼并前史
$ git log --graph
# 每条日志一行显现
$ git log --pretty=oneline
# 仅显现 SHA-1 校验和一切 40 个字符中的前几个字符
$ git log --abbrev-commit
# --pretty=oneline --abbrev-commit 合用的简写。
$ git log --oneline
# 仅显现作者匹配指定字符串的提交。
$ git log --author='xxx'
#
$ git --no-pager log
# Log files that have been moved or renamed
$ git log --name-status --follow -- file
git diff
# 比较作业区与暂存区之间的不同
$ git diff
# 比较暂存区与本地库房之间的不同
$ git diff —cached(git diff —staged)
# 比较作业区和暂存区(即一切未提交到本地库房的修正)与本地库房当时的HEAD之间的不同
$ git diff HEAD
# 比较作业区和暂存区(即一切未提交到本地库房的修正)与本地库房dev分支最新commit之间的不同
$ git diff dev
# 比较作业区和暂存区(即一切未提交到本地库房的修正)与本地长途盯梢dev分支最新commit之间的不同
$ git diff origin/master
# 比较两次提交之间的不同
$ git diff [commit_sha1_value] [commit_sha1_value]
git tag
有两种tag,一种是lightweight,轻量标签;一种是annotated tag,附注标签
# 显现一切
$ git tag
# 创立lightweight tag(轻量标签)
# 假定没有写commit_sha1_value,则会主动把tag放到现在的这个commit上
$ git tag <tag_name> [commit_sha1_value]
# 创立annotated tag(附注标签)
# 假定没有写commit_sha1_value,则会主动把tag放到现在的这个commit上
$ git tag -a <tag_name> -m <tag_message> [commit_sha1_value]
# 删去tag
$ git tag -d <tag_name>
# 检查某个commit上的标签
$ git tag --points-at <commit>
轻量标签很像一个不会改动的分支——它仅仅某个特定提交的引证。
附注标签是存储在
Git
数据库中的一个完整git的tag类型的objects方针, 它们是能够被校验的,其中包括打标签者的姓名、电子邮件地址、日期时刻, 此外还有一个标签信息。
git show
# 显现tag对应的commit所提交的内容,假定是附注标签,仍是显现附注标签的信息
$ git show <tag_name>
# 显现某次commit提交的内容
$ git show <commit_sha1_value>
git branch
# 检查本地库房分支
$ git branch
# 检查长途库房分支
$ git branch -r
# 检查本地库房和长途库房分支
$ git branch -a
# 创立本地库房分支
$ git branch <branch_name>
# 强制删去本地库房分支
$ git branch -D <branch_name>
# 删去本地库房分支
$ git branch -d <branch_name>
# 检查分支详细信息,包括分支终究一个commit的hash、message等
$ git branch -v
# 同git branch -v
$ git branch -vv
# 修正本地库房分支称号,假定省掉old_branch_name,则更改的是当时分支的称号
$ git branch -m <old_branch_name> <new_branch_name>
# 强制修正本地库房分支称号
$ git branch -M <old_branch_name> <new_branch_name>
# 检查哪些分支现已兼并到当时分支
$ git branch --merged
# 检查哪些分支未兼并到当时分支
$ git branch --no-merged
git branch -d <branch_name>
:假定该分支还未合入master或许main,会提示报错,不让删去
git branch -vv
:一起还会显现每一个分支正在盯梢哪个长途分支
git checkout
# 切换到新分支
$ git checkout <branch_name>
# 创立并切换到新分支
$ git checkout -b <branch_name>
# 重置分支,删去已存在的分支且从头创立,分支不存在也不会报错称
$ git checkout -B <branch_name>
# 将head指向一个commit
$ git checkout <commit_sha1_value>
# 从某个本地长途盯梢分支中检出一个新分支(并设置该分支的上游是长途盯梢分支)
$ git checkout -b <new_branch_name> <remote_name>/<old_branch_name>
# 是 git checkout -b <new_branch_name> <remote_name>/<old_branch_name>的简写
$ git checkout --track <remote_name>/<branch_name>
# 让作业区中的一切文件吊销更改
$ git checkout -- .
# 让作业区中的某些文件吊销更改
$ git checkout -- <file_name> <file_name>
git checkout -b <new_branch_name> <remote_name>/<old_branch_nameh>
git checkout --track <remote_name>/<branch_name>
git checkout <branch_name>
git checkout -b <new_branch_name> <remote_name>/<old_branch_nameh>
的意思是从某个本地长途盯梢分支中检出一个新分支,并设置该新分支的上游是该本地长途盯梢分支; 因为git checkout -b <new_branch_name> <remote_name>/<old_branch_nameh>
经常用,且检出的新分支姓名和其上游分支的姓名一般相同,不太会取不同的姓名;所以出了一个简写指令git checkout --track <remote_name>/<branch_name>
;git checkout --track <remote_name>/<branch_name>
该指令从某个本地长途盯梢分支中检出一个新分支,并设置该新分支的上游是该本地长途盯梢分支,一起该新分支的姓名不能指定,只能是该本地长途盯梢分支的姓名;git checkout --track <remote_name>/<branch_name>
仍是太长;所以git checkout branch_name
切换分支时,先从本地库查找分支,在本地库没找到时,会去本地长途盯梢分支中查找,假定本地长途盯梢分支中有相同称号的分支,则也会检出分支并设置其上游为同名的本地长途盯梢分支;假定本地长途盯梢分支里也没有找到就会报错;
git checkout <commit_sha1_value>
:这样会产生detached head,即head
不再指向一个分支,而是指向一个commit
; 运用场景是比方从之前的commit
或许误删的commit
(经过给git reflog
检查);拉出一个新分支;
# 检查一切操作的日志
$ git reflog
# 检出需求检出的commit
$ git checkout <ommit_sha1_value>
# 检出一个新的分支
$ git checkout -b <new_branch_name>
git checkout --
的吊销功用:git checkout
吊销的是作业区的内容,即铲除作业区 场景一、本地库中已有user.txt
,在作业区修正了该文件,可是没有提交到暂存区,此刻吊销更改是从本地库房中康复内容 场景二、本地库中已有user.txt
,在作业区修正了该文件,而且之前按已提交到暂存区,此刻吊销更改是从暂存区中康复内容
git restore
代替git checkout
的吊销功用。
# 放弃在作业区的修正
$ git restore <file_name> <file_name>
# 放弃一切文件在作业区的修正
$ git restore .
# 将暂存区的内容,移动作业区中,便是git add的反向操作
$ git restore —staged <file_name> <filen_ame>
git restore <file_name> <file_name>
代替git checkout -- <file_name> <file_name>
git restore .
代替git checkout -- .
it restore —staged <file_name> <filen_ame>
:git add
的反向操作
git switch
代替git checkout
的切换分支功用。
# 假定本地库房或许本地长途盯梢分支有这个分支,则切成功,不然失利
$ git switch <branch_name>
# 创立并切换到新分支
$ git switch -c <branch_name>
# 重置分支,删去已存在的分支且从头创立,分支不存在也不会报错称
$ git switch -C <branch_name>
git switch <branch_name>
代替git checkout <branch_name*>
git switch -c <branch_name>
代替git checkout -b <branch_name>
git switch -C <branch_name>
代替git checkout -B <branch_name>
git switch -
能够快速切换上一个分支,来回切换,与cd -
相同
git remote
# 显现长途库房的姓名
$ git remote
# 显现长途库房的姓名及url
$ git remote -v
# 检查本地长途盯梢分支与长途库房中分支的同步情况
$ git remote show <remote_name>
# 能够删去(在长途库房中被删去的分支)对应的本地长途盯梢分支
$ git remote prune <remote_name>
git remote show <remote_name>
:一般运用场景便是在git fetch
之前检查一下分支同步情况
git fetch —prune
与git remote prune
的作用相同,实际上删去(长途库房中被删去的分支)对应的本地长途盯梢分支。
git rebase
变基
$ git rebase <upstream_name>
# 当时分支为dev
$ git rebase main
# 假定有冲突,处理冲突后继续编辑
$ git rebase —continue
# 当时分支为main
$ git merge dev
git rebase <upstream_name>
做了什么?git rebase main
(dev
)把dev
分支的提交重放(从头运用)到main
分支的顶部。
git rebase --onto main server client
做了什么? 关于这个指令,每次看到都头大,需求自己用文字描绘一下,以方便了解
# newbase_name\upstream_name\branch_name既能够是分支名,也能够是commit_sha1_value
$ git rebase [--onto <newbase_name>] [<upstream_name> | [branch_name]]
怎样了解上面这条指令各个参数是啥意思?列出详细指令来尝试解说
-
场景及指令一:
场景:假定dev
是从master
检出的分支,要在dev
分支上变基,当时地点分支不是dev
分支
指令:git rebase <upstream_name>
:git rebase master
# 切换到dev分支 git checkout dev # rebase master,这个master是对应upstream_name;怎样了解这里的上游分支 # 实际上便是dev是从master检出的,是dev的上游分支,依此来找到两个分支的穿插点 # 把在dev分支上以这个穿插点为起点,以当时HEAD为结尾(dev最新commit),把这两点之间的 # commit在master分支顶部(最新commit),从头来一遍,得到一个新的dev分支。 git rebase master
-
场景及指令二:
场景:假定dev
是从master
检出的分支,要在dev
分支上变基,当时地点分支不是dev
分支
指令:git rebase <upstream_name> [branch_name]
:git rebase master dev
# git rebase master dev 是 git checkout dev + git rebase master 这两条指令的简写 # 便是我先切到dev分支,再rebase master分支 git rebase master dev
-
场景及指令三:
场景:假定当时地点分支是dev
分支,其本地长途盯梢分支是origin/dev
指令:git rebase
# git rebase 是 git rebase origin/dev 指令的简写 git rebase
简写的条件是
- 当时不是detached headhead状况
- 当时分支有对应的本地长途盯梢分支(即上游分支)
-
场景及指令四:
场景:git rebase --onto main server client
# 第一步:git checkout client # 第二步:找到client与其上游分支server的穿插点的之后的一切commit # 第三步:把这些commit根据--onto参数的值main顶部(最新的commit),重放这些commit # 了解分为两部分,第一部分找server client穿插之后的提交, # 第二部分,以--onto参数的值为基,重放这些提交 git rebase --onto main server client
-
场景及指令五:
场景:master
分支,共6个提交,每个提交都创立一个txt
文件 指令:git rebase --onto HEAD~5 HEAD~3 HEAD
# 第一步:git checkout HEAD,处于detached headhead状况 # 第二步:找到HEAD~3与HEAD之间一切的commit # 第三步:把这些commit根据HEAD~5,重放这些commit # 实际效果便是删去第2次与第3次提交 # 能够从当时游离的head检出一个分支代替master,或许直接git branch -D master git rebase --onto HEAD~5 HEAD~3 HEAD
- 运用场景
- 在兼并分支前,不想分叉,能够先
rebase
方针分支,再合入方针分支 - 同步长途分支时,不运用
git pull
,运用git fetch
,再运用git rebase
- 在兼并分支前,不想分叉,能够先
同享分支:当一个分支会被
push
到长途库房,且有或许其他人会进行pull
操作时,这便是一个同享分支
Do not rebase commits that exist outside your repository and that people may have based work on.
永久、永久不要对一个同享分支进行变基。
原因便是:变基操作的实质是丢掉一些现有的提交,然后相应地新建一些内容相同但实际上不同的提交。
根据变基的实质,假定是多人协作对同享分支允许变基;假定A在本地变基操作后推到了长途同享的分支,一起也丢掉了一些现有的提交;
而B在拉去长途同享分支时,因为依靠了之前A丢掉的提交,所以假定再merge后推送到长途,就会造成重复的提交。
处理办法:那便是永久不要对同享分支进行变基;
交互式变基
# start_commit_sha1_value不包括,end_commit_sha1_value包括
# end_commit_sha1_value能够没有,则默许为当时分支的HEAD
$ git rebase -i [start_commit_sha1_value] [end_commit_sha1_value]
# 假定你异常退出了变基选择操作的窗口,运用以下指令从头翻开
$ git rebase --edit-todo
# 放弃变基
$ git rebase --abort
# 保存,啥也不动
**p, pick <commit> = use commit**
# 只修正提交信息
**r, reword <commit> = use commit, but edit the commit message**
# 不仅仅修正提交信息
**e, edit <commit> = use commit, but stop for amending**
# 并入前一个提交
**s, squash <commit> = use commit, but meld into previous commit**
# 并入前一个提交,并丢掉该提交信息
**f, fixup [-C | -c] <commit> = like "squash"
but keep only the previous commit's log message,
unless -C is used,in which case keep only this commit's message;
-c is same as -C but opens the editor
# 删去该提交
**d, drop <commit> = remove commit**
主张运用vscode
中的GitLens
插件来进行交互式变基,如下图
git fetch
会拉去数据,一起会同步一切长途库房分支和本地长途盯梢分支,关于本地长途盯梢分支,实际上便是为了区分本地库房分支,前面加了remote_name
的分支引证
git fetch
指令做了什么?
- 拉取它的一切数据
- 更新你的长途盯梢分支
- 对与长途库房中有而本地没有的分支,只会创立长途盯梢分支,不会创立本地分支
当抓取到新的长途盯梢分支时(这句话的意思是比方长途库房新建了一个分支dev,当git fetch
时就会拉取新长途分支到本地的长途盯梢分支origin/dev
),但不会创立一个本地dev
分支。
- 怎样仅仅想兼并到你的分支,能够履行
git merge origin/dev
- 假定想在本地分支的作业,能够从
origin/dev
检出一个本地的dev
分支,履行git checkout -b dev origin/dev
# 从长途库房中拉去一切分支数据到本地,同步一切长途库房分支和本地长途盯梢分支,假定缺省长途库房名,默许为origin
$ git fetch <remote_name>
# 从长途库房中只拉取一个分支数据到本地
$ git fetch <remote_name> <remote_branch_name>
# 从长途库房中只拉取一个分支数据到本地,并在本地库房中创立一个分支
$ git fetch <remote_name> <remote_branch_name>:<local_branch_name>
# 首要会同步长途库房分支与本地长途盯梢分支,一起会将本地长途盯梢分支中存在而长途库房分支没有的分支删去。
$ git fetch —prune
# 显现fetch的详细信息
$ git fetch -v
git fetch —prune
:比方初始状况时长途库房分支和本地长途盯梢分支现已同步; 此刻,在长途库房中删去某个分支a
,再运用git fetch
时,本地长途盯梢分支中的分支a
不会删去; 此场景下能够运用git fetch —prune
,也能够运用git remote prune <remote_name>
- 运用
- 运用一
git fetch origin master
//从长途origin
库房拉取master
分支的数据,一起同步本地长途盯梢分支master
git log -p master origin/master
//比较本地库房的master
分支和本地长途盯梢分支master
的差异
git merge origin/master
//将本地长途盯梢分支中的master
分支合入本地库房的master
分支 - 运用二
git fetch origin master:temp
//从长途的origin
库房拉取master
分支的数据,并在本地库房中新建一个分支temp
git diff temp
//比较本地库房当时分支和本地库房temp
分支的不同
git merge temp
//兼并本地库房temp
分支到本地库房master
分支
git branch -d temp
//删去本地库房temp
分支
- 运用一
git merge
# 默许选用fast forward
$ git merge
# 选用fast forward
$ git merge -ff
# 强行封闭fast forward
# 个人觉得运用场景是:拉取长途分支,检出自己的分支上开发,然后push前rebase一下长途分支,提个pr,选用git merge --no--ff的办法merge到长途分支。
$ git merge --no-ff
-
fast forward
:这时候bugfix
合入master
是一次fast forward
3 way merge
假定现已分叉了,还想完结
fast-forward
的merge
,能够运用git rebase
git pull
git fetch
+ git merge
# git fetch + git merge
$ git pull
# git pull的简写
$ git pull --merge
# git fetch + git rebase
$ git pull --rebase
# 显现详细信息
$ git pull -v
git push
将本地库房当时分支推出送长途分支
# 完整指令,关于没有设置上游的本地分支推送至长途选用的办法
$ git push <remote_name> <local_branch_name>:<remote_branch_name>
# 假定本地分支名和长途分支名相同的情况下,能够省掉:<remote_branch_name>
$ git push <remote_name> <local_branch_name>>
# 设置当时的分支的上游分支是
$ git push —set-upstream <remote_name> <remote_branch_name>
# git push -u origin是git push —set-upstream origin的简写
$ git push -u <remote_name> <remote_branch_name>
# 删去长途分支
$ git push <remote_name> -d <remote_branch_name>
# 删去长途分支
$ git push <remote_name> :<remote_branch_name>
# 推送某个标签
$ git push <remote_name> <tag_name>
# 一次性推送很多标签
$ git push origin —tags
# 删去长途标签的办法
$ git push origin --delete <tag_name>
git push
简写指令运用条件条件是:
- 长途库房有这个分支
- 而且经过
git branch -vv
检查,本地库房当时分支与本地长途盯梢分支是关联的- 而且当时只要一个
origin
的remote
git push <remote_name> <local_branch_name>
:将本地库房分支推送到长途库房;这样操作,虽然会一起更新本地长途盯梢分支;并没有将本地的该分支与对应的本地长途盯梢分支进行关联(经过git branch -vv
检查)
新建本地分支后
push
到长途库房,但并没有将本地分支与对应的本地长途盯梢分支相关联,下次本地分支有新的commit
后,再push
到长途,仍然要git push <remote_name> <local_branch_name>
,不能直接用git push
这样的简写指令
git push -u <remote_name> <remote_branch_name>
:将新建的本地分支推送到长途分支,并将该分支与对应的本地长途盯梢分支相关联,下回再推送时就能够运用git push
这样的简写
git revert
git revert <commit_sha1_value>
git revert HEAD
git revert HEAD^
git revert HEAD~
下图是在C5
为当时HEAD
,别离对C5
、C4
、C3
、C2
、C1
、C0
进行revert
差异:
HEAD^
首要是控制merge
之后回退的方向;HEAD~
才是回退的步数 个人了解:假定某个节点只要一个父节点,那就用~
,不要用,因为不太直观,简单混乱;只针对有多个父节点的回退操作选用。
git revert -m <commit_sha1_value>
git revert -m HEAD
git revert -m HEAD^
git revert -m HEAD~
revert首要分两类,一类是针对只要一个父节点的commit,一类是针对有两个父节点的commit(merge分支产生的)
什么时候加-m,当该节点是merge产生的节点的时候,它会有2个父节点(之前老是记不清,一个commit节点是不或许有多于2个父节点的,经过这个-m的参数才想起来,所以这个-m后边跟的数字只能是1和2,1代表我保存自己的分支,2代表保存合入的分支)
revert
或许带来的问题如下图描绘
关于此问题官网给出的处理方案是在master
上revert
掉之前的revert
,然后再merge
git reset
# 更改HEAD和当时分支顶部指向哪个commit,并掩盖暂存区
git reset —mixed <commit_sha1_value>
# 只更改HEAD和当时分支顶部指向哪个commit
git reset —soft <commit_sha1_value>
# 更改HEAD和当时分支顶部指向哪个commit,并掩盖暂存区和作业区
git reset —hard <commit_sha1_value>
# git reset —mixed <commit_sha1_value>简写
git reset <commit_sha1_value>
git reset —soft
git reset —mixed
git reset —hard
下图是在C5
为当时HEAD
,别离reset
到C4
、C3
、C2
、C1
、C0
能够运用的指令
revert
与reset
的差异是什么
git revert
是用一次新的commit
来回滚之前的commit
,此次提交之前的commit
都会被保存;git reset
是回退到某次提交,提交及之前的commit
都会被保存,可是此之后的commit
都会被删去;所以能够说revert
是以新增commit
的办法回滚某个commit
;而reset
是回退到某个commit
单从用法上来讲,运用场景能够参考以下: 找出有问题的
commit
,假定从HEAD一直到有问题的commit
之间都不要,那就用reset
;假定从HEAD
一直到有问题的commit
之间,只想回滚有问题的commit
,中心其他的commit
还要保存,那就用revert
以上过于啰嗦了,简单点,便是回滚某个
commit
用revert
,回退到某个commit
用reset
;所以关于git reset HEAD
这个指令是无意义的,当时就在这个commit
,要回退到这个commit
岂不是无用功;关于git revert HEAD
这个指令是有意义的,假定你的确想回滚当时的commit
git stash
# 保存作业区暂存区中的内容
git stash
# 保存作业区暂存区中的内容,并增加注释,不引荐运用
git stash save 'message'
# 保存作业区暂存区中的内容,并增加注释,引荐运用
git stash push -m 'message'
# 康复后一起弹出 stash
git stash pop
# 康复后stash内容并不删去
git stash apply
# 删去stash
git stash drop
# 清空`stash`
git stash clear
# 显现一切的stash
git stash list
# 显现最新缓存修正的计算信息
git stash show
在运用
git stash pop
代码时,经常会碰到有冲突的情况,一旦出现冲突的话,体系会以为你的stash
没有结束。导致的结果是git stash list
中的列表仍然存在,实际上代码现已pop
出来了。
- 运用场景
- 正常dev分支上开发,紧迫bug或许功用来时,能够先将在dev分支做的作业用
git stash save
存下,然后切换到紧迫分支,修正或许完结commit
之后,在切回dev分支,用git stash pop
将之前的作业内容回复
- 正常dev分支上开发,紧迫bug或许功用来时,能够先将在dev分支做的作业用
Git中的其他概念及指令
本地长途盯梢分支 上游分支
从一个长途盯梢分支检出一个本地分支会主动创立所谓的盯梢分支(它盯梢的分支叫做上游分支,即盯梢的是长途库房的分支); 盯梢分支是与长途分支有直接关系的本地分支; 假定在一个盯梢分支上输入 git pull
,Git
能主动地识别去哪个服务器上抓取、兼并到哪个分支。
ORIG_HEAD
ORIG_HEAD
记录了reset
或许merge
操作之前的HEAD
运用场景:
- 使用
ORIG_HEAD
吊销reset
:git reset ORIG_HEAD
- 使用
ORIG_HEAD
吊销merge
:git reset --merge ORIG_HEAD
use –merge flag to preserve any uncommitted changes
FETCH_HEAD
记录了长途一切分支对应的最新的commit
git ls-files -s
检查索引区内容
git cat-file
# 检查git object内容
git cat-file -p <sha1_value>
# 检查git object类型
git cat-file -t <sha1_value>
# 检查git object巨细
git cat-file -s <sha1_value>
git objects
有四种类型:blob
、commit
、tree
、tag
通用数据结构为:
blob
# echo -n输出的内容不换行
echo -n 'Hello, World!' | git hash-object --stdin
b45ef6fec89518d314f546fd6c3025367b721684
# echo -e转义
echo -e -n 'blob 13\0Hello, World!' | openssl sha1
(stdin)= b45ef6fec89518d314f546fd6c3025367b721684
git add .
会生成blob
方针
blob
方针存储文件内容信息,包括sha1
、字节巨细、文件内容数据
tree
git commit
会生成tree
方针(或许有多个)
tree
方针中嵌套tree
以来表明文件的嵌套
blob
方针不存储文件的称号,文件的称号存储在tree
方针中
commit
git commit
会生成一个commit
方针(包括)、tree
方针(可有有多个),不会生成blob
方针
tag
git tag -a tagname
会创立一个tag
方针,方针中的object
会指向某一个commit
;tag
方针会包括一些作者和时刻的信息等等
git tag <tag_name>
不会创立一个tag
类型的git object
git references
git中的引证实际上是指向某个commit的指针
Tags
Lightweight tags
的引证是指向某个commit
类型的git object
方针的指针
ANNOTATED tags
的引证时指向某个tag
类型的git object
方针的指针
Branches
Branches
的引证是指向某个commit
类型的git object
方针的指针
HEAD
一般是指向当时分支的引证,可是它也能够指向某个commit
类型的git object
方针(detached HEAD
)
git show-ref
# 检查当时一切的tag,约同等与 git tag
git show-ref --tags
# 检查当时一切的分支,约同等与 git branch
git show-ref --heads
git gc
因为git
是全量快照,每一次commit
都会对应一个版别的悉数数据,这样会造成库房很大,为了处理该问题,引入了紧缩算法,举例,git clone
在拉取长途库房时,就会紧缩成pack
后再传递;在本地履行gc
后,也会把.git/objects
文件夹下的方针紧缩到pack
文件夹下。
参考文献
- Git – Book (git-scm.com)
- Git In-depth
本文发布内容来自个人关于Git-scm网站关于Pro Git book的阅览及实践后的了解,一起参考了Git In-depth视频,文章未经授权禁止任何形式的转载。