Git学习笔记v4.0

文章目录

Git最小配置

添加配置

git config [--local | --global | --system] user.name 'Your name' 
git config [--local | --global | --system] user.email 'Your email'
  • local:作用区域为本仓库,配置文件在.git/config
  • global: 作用为当前用户的所有仓库,配置文件在个人home目录下的.gitconfig里面
  • system: 本系统的所有用户(这个基本不用),配置文件应该在git安装目录下

优先级:local > global > system

查看配置

git config #出现这个命令下可以添加的参数
git config --list #出现local、global、system三个范围的配置
git config [--local | --global | --system] --list #指定范围内的配置信息 这个指令添加local参数时候需要进入某个仓库里面才能使用,不然会提示错误

清除配置

git config --unset [--local | --global | --system] user.name 'Your name'

建立Git仓库(两种情景)

1、把已有的项目代码纳入Git管理

$ cd 项目代码所在的文件夹
$ git init #初始化仓库,当前文件夹下会创建一个.git的隐藏文件

2、新建的项目直接用Git管理

$ cd 某个文件夹
$ git init your_project  #会在当前路径下创建和项目名称同名的文件夹
$ cd your_project

往仓库添加文件

添加流程

graph LR
A(工作目录)-->|git add files|B(暂存区)
B(暂存区)-->|git commit|C(版本历史)

添加到暂存区

    进入到项目目录使用git add指令,其中

  • git add . ++添加当前目录的所有文件到暂存区++
  • git add ‘文件名字’ ++添加指定的文件到暂存区++
  • git add -u ++工作区中所有被跟踪后(即之前有add这个文件)修改过的文件一起提交到暂存区++
在暂存区的文件可保留一套与目录中不一样的方案(但是又还没有成为一个版本历史),
如果当前目录的文件出现错误或者比之前一套还差,可以从暂存区把之前的文件回退到当前目录。

提交到版本库

    当一次或者几次执行git add命令后,暂存区会有响应的文件生成,但是还没有提交,接下来就要执行git commit命令来进行提交到本地仓库。

  • git commit ++直接提交++
  • git commit -m’提交说明’ ++带有提交说明的一次提交,可从提交日志中看到这些信息++

Git文件重命名

文件状态:文件已经被Git管理,如果未被管理改名字和Git不是很大关联。

1、普通方式重命名

    我们在命令框中对某个文件重命名一般是如下的步骤:

mv 'file_name' 'new_file_name' #这个时候使用git status会提示之前的文件被删除了,同时新增了一个文件
git add 'new_file_name' #然后使用add指令提交新的文件
git rm ''file_name #再使用rm 指令删除已被替换的文件

2、Git提供的文件重命名方式

    经Git管理的文件修改名字只需要一行Git命令

git mv 'file_name' 'new_file_name' #效果和上面的方式是相同的,省去了add和rm可以直接进行commit

查看版本库(git log)

–all,–oneline,–graph可以自由组合

git log #查看版本历史
git log -all #查看所有包括分支在内的版本历史
git log --all --graph #图形化分支版本历史
git log --oneline #查看版本历史(简洁,顾名思义每个版本一行信息)
git log --oneline --all #查看所有版本历史包括所有的分支
git log master #查看master这一支下所有,也可以写其他分支的名字
git log -n #查看最近的n个版本历史
git log -n --oneline #查看最近的n个版本历史(每个版本单独一行显示)

查看.git目录

HEAD

    存储当前工作所在的分支,即指向一个引用,refs下的分支。代表整个仓库当前的工作在哪一个分支上。

config

    存储和本地仓库有关的信息,包括了用户名和邮箱(最初配置的user.name和user.email)

refs

    包含了heads(分支)和tags。

  • heads对应的是分支,分支相当于一个独立的开发空间,例如前后端开发可以事先建立两个分支,互不影响。需要集成时,两个分支又可以一起集成到一个公共的分支上去。其中会有master或者更多的分支,例如master存放的是一个对象,使用git cat-file -t '版本号’可以查看这个对象的类型为commit类型。

  • tags有时候也叫做“里程碑”,项目开发到一个程度,有可观的成果了就打上一个标签,例如v1.0。

objects

   在objects文件夹下面存放了许多文件夹(有数字和字母组成,例如4b、4d、da),还有一种类型是pack类型,git会做一个自我梳理的过程,如果松散的文件比较多,会进行打包。


   此处使用git cat-file 命令查看文件需要输入hash值时,需要把文件名和在文件夹下的字符串放一起形成一个hash值。(举个例子,如果文件名是e8,cd e8后执行 ls -al,出现a424871993a81bf460564d5eb8d294c5253b6f,合并后形成一个hash值就是e8a424871993a81bf460564d5eb8d294c5253b6f)


   objects文件夹下通常包含两种类型的对象tree和blob。

Git核心对象(commit、tree、blob)

对象之间的关系

commit

    每一次执行commit命令都会生成这样的一个对象,使用git log命令可以查看这类对象,一个commit会对应一棵树(不会对应两棵树)。这棵树代表了commit对应的视图,视图存放了快照,快照的集合里面放了当前commit对应的本项目仓库的所有的文件夹以及文件的快照(即某次执行commit时候的文件目录结构)

tree

    类似于文件夹

blob

    tree的叶子节点,对应一个文件,blob和文件名没有关系,只要文件内容相同,在整个git仓库中只有一个blob(唯一),不会因为文件名不同而存在两份相同内容的blob。

分离头指针情况下的注意事项

    git checkout 一般用来切换分支或者创建分支,如果不小心执行了某个指令可能分离了头指针
例如

git checkout 'commit的hash值'

    分离头指针状态本质上是指正工作在一个没有分支的状态下。为什么说这个状态比较危险呢?因为这个状态下提交的commit并没有和其他分支有关联,如果切换了分支,分离头指针状态下的commit最后很可能被git当做垃圾清除掉。


    但是分离头指针也有好处,当自己需要对程序进行尝试性的更新或者其他不确定性操作,变更后发现并没有达到自己预期那就可以随时把这个变更丢弃(切换到新的分支就可以了)

Git修改已提交commit的message信息

修改最近一次commit的message

执行

git commit --amend

进入编辑模式,这个commit是所在分支的最新的commit

修改之前commit的message

执行

git rebase -i '要修改的commit的父级commit的hash值'

进入交互模式。


    页面会罗列出基于这个commit的所有子commit,根据编辑框提示,自主选择pick、reword、edit等,也可以使用简写pick->p、reword->r…,保存退出进入新的交互页面,输入新的message后保存退出即可查看。

    git rebase会涉及到变基操作,分离头指针。rebase意味着基于新的base的commit来变更部分commits。它处理的时候,把HEAD指向base的commit,此时如果该commit没有对应branch,就会处于分离头指针状态,然后重新一个一个生成新的commit,当rebase创建完最后一个commit后,结束分离头指针,Git让变完基的分支指向HEAD。

合并commit

合并连续的commit

执行

git rebase -i '要合并的commit的父级commit的hash值'

进入交互模式,要合并几个commit,必须要选择一个commit为合并项,即必须有一个commit为pick,其他需要合并的commit设置为squash,也可以简写s。保存退出之后会进入一个新交互页面显示要合并的commit,也可以为合并后的commit添加message(在第一行说明后添加)。

合并间隔的commit

    仍然使用

git rebase -i '要合并的commit的父级commit的hash值'

要合并的commit是最上级的情况

    这个时候第一个commit已经是最上级了,它没有父级commit了,如果要合并它,那就在git指令后跟上它的hash值。这样进入交互页面,我们能看到它的子级commit,但是没有它自身。


举个例子比如git log显示的commit是这样的

commit 464746a(HEAD -> master)
commit 4611891
commit 43c6742

那么执行 git rebase -i 43c6742 交互页面是这样的:

pick 464746a commit的message  #这个不是需要合并的commit
pick 4611891 commit的message  #这个是需要合并的commit

那就需要最上面手动加上hash值为43c6742的commit,并且把需要合并的commit放在一起并把pick改为squash。类似这样:

pick 43c6742 # message不写也无所谓
pick 4611891 commit的message  #这个是需要合并的commit
pick 464746a commit的message  #这个不是需要合并的commit

这个情况会有很多提示信息,根据提示一步步完成就可以。(合并后可能会出现两个没有父级的commit,即两棵树,如果有多次合并可能就会有多个)

工作区、暂存区、HEAD所存文件之间的比较和恢复

比较暂存区和HEAD所含文件的差异(git diff)

    HEAD所含的文件即最新的一次commit。出现的减号加号表示变更。

git diff --cached # 比较暂存区和HEAD文件
git diff --staged # staged和cached一样,都是指暂存区

比较工作区和暂存区所含文件的差异

git diff # 默认比较工作区和暂存区的区别(比较所有文件)
git diff -- '文件名' # 比较工作区和暂存区指定文件的差异

把工作区、暂存区恢复成和HEAD一样

git reset --hard HEAD # 此命令执行后工作区、暂存区和HEAD文件一样

把暂存区还原成和HEAD所存文件一样的状态

恢复所有文件

git reset HEAD # 恢复暂存区和HEAD一样

选择暂存区中的某些文件恢复

git reset HEAD -- '文件名'  #恢复指定文件和HEAD一样,后面可以跟多个,用空格分开

把工作区的文件恢复为和暂存区一样的状态

git checkout # 显示缺少的文件
git checkout -- '需要恢复的文件名' # 恢复指定文件工作区和暂存区一样

消除最近的几次commit

这条命令慎用

git reset --hard 'commit版本号(hash值)' # 工作区、暂存区和HEAD都恢复成了这个commit的文件情况

消除最近的提交

git reset --hard HEAD~1 #版本回退一级并清除暂存区,写2即回退两级,依次类推
git reset --hard HEAD^ # 回退一个版本,作用和HEAD~1是一样的

比较不同commit之间同个文件的差异

直接比较分支也是可以的,使用

git diff '分支名1' '分支名2' # 比较两分支所有的文件

这样会显示很多的不同,比较杂乱。可以直接选择commit进行比较

git diff 'commit版本号' 'commit版本号' -- '文件名' # 比较两个commit之间同个文件的差异,可以用空格分开比较多个文件

或者是两个分支之间同个文件的比较

git diff '分支名1' '分支名2' -- '文件名'  # 空格分开增加多个文件进行比较

Git正确删除文件的方法

普通的删除方式即

rm '文件名'

但是这样还需要使用add指令提交到暂存区,这里可以使用和 git mv 指令类似的 git rm

git rm '文件名' # Git提供的快捷删除指定文件,直接提交到暂存区,不需要在工作目录下先删除

开发中加塞了紧急任务需要存储当前工作区(stash)

比如,当前正在开发A.java文件,此时因为其他情况需要修改这个A.java变成其他的模样,可以使用

git stash

命令来存储当前的文件,使用

git stash list

可以查看临时储存的文件(类似于堆栈),当临时工作做完后,可以使用

git stash apply

让存储的文件从堆栈中恢复到工作区,但是堆栈里还会保留,使用git stash list还是可以看到,但是如果使用

git stash pop

堆栈中就不再保留。

配置公私钥

众所周知ssh key是加密传输。加密传输的算法有好多,git使用rsa,rsa要解决的一个核心问题是,如何使用一对特定的数字,使其中一个数字可以用来加密,而另外一个数字可以用来解密。这两个数字就是你在使用git和github的时候所遇到的public key也就是公钥以及private key私钥。其中,公钥就是那个用来加密的数字,这也就是为什么你在本机生成了公钥之后,要上传到github的原因。从github发回来的,用那公钥加密过的数据,可以用你本地的私钥来还原。如果你的key丢失了,不管是公钥还是私钥,丢失一个都不能用了,解决方法也很简单,重新再生成一次,然后在github.com里再设置一次就行

检测是否已经存在公私钥

cd ~/.ssh

进入.ssh文件后使用ls -al,如果存在三个文件就说明已经存在公私钥

生成公私钥

ssh-keygen -t -rsa -b 4096 -C "邮箱地址"

同步本地仓库到GitHub

git remote add '站点名字' 'ssh协议' # 站点名字可以自己取,一般为origin

但是如果远程仓库带有类似README.md这样预先创建的文件,本地却还没有就会报错,就需要先使用pull命令或者fetch命令先把远端的文件同步到本地
比如使用:

git fetch '站点名' '分支名' 

就可以把远端的指定分支拉取到本地,这个时候使用gitk指令可以看到又出现一棵独立的树(non-fast-forwards),这个情况下本地做push,远端是会报错的(同个分支情况下)

non-fast-forwards错误

这个错误经常出现在本地分支和远程分支不同步的情况,可以使用rebasemerge指令来解决

merge

比如远端的master分支和本地的master分支不一样,先切换到master分支

git checkout master

然后

git merge --allow-unrelated-histories '设定的远程站点名'/master  # 因为是合并不想管的两棵树,所以需要加--allow-unrelated-histories

从远端仓库clone到本地

git clone 'ssh协议' # 克隆一份仓库到本地

如果没有指定本地仓库名字,会默认是ssh协议最后.git前面的那个文件名

团队合作中避免使用的命令

git push -f # 会突破Git本身的安全机制,即使不是fast-forwards也能push到远端

团队工作流

主干开发

适用于组件开发的团队,成员能力强,人员少,沟通顺畅

Git Flow

适用于不具备主干开发能力。有预定的发布周期,需要执行严格的发布流程。

GitHub Flow

适用于不具备主干开发能力。随时集成随时发布:分支集成时经过代码评审和自动化测试就可以立即发布的应用。

GitLab Flow(带生产分支)

适用于不具备主干开发能力。无法控制准确的发布时间,但又要求不停地集成。

GitLab Flow(带环境分支)

适用于不具备主干开发能力。需要逐个通过各个测试环境的验证才能发布。

GitLab Flow(带发布分支)

适用于不具备主干开发能力。需要对外发布和维护不同版本。

选择合适的分支集成策略

在Repository的Settings页面可以勾选Merge Button,

  • Allow merge commits
  • Allow squash merging
  • Allow rebase merging


    都勾选了就可以在使用的时候进行选择。
    image

在远程仓库的选项中选择Pull requests,然后选择New pull request,然后选择要合并的分支和要被合并的分支,点击Create pull request,页面就可以选择三种分支集成方式。

Create a merge commit

比如有master分支和a分支,a合并到master上去,选择这种合并方式,生成一个新的commit,并且master和a的指针都指向这个commit

Squash and merge

这种合并方式,不会把a的指针指向新的commit(相当于a不改变),在master上会新生成一个新的集成了a分支上所有commit的一个完整的commit。可以理解为把a分支的所有commit合并然后添加在master上。

Rebase and merge

这种方式合并,也不会把a的指针指向新的commit(相当于a不改变),在master上新生成n个commit(n=a分支上不同的commit个数)。


Squash和Rebase这两种方式都不动a分支。

举个例子,在没有进行分支合并集成之前是这样:
image


使用第一种方式

image

使用第二种方式

image

第三种方式

image


Git中常用指令总结(非全部,git-bash)

git add 命令

git add #添加到暂存区

git branch 命令

git branch #查看分支(不包含详细信息)
git branch -v #查看本地的分支
git branch '分支名字' #创建分支
git branch -D '分支名字' #强制删除分支

git cat-file 命令

git cat-file -t '对象hash值'  #显示对象类型
git cat-file -p '对象hash值'  #显示对象内容
git cat-file -s '对象hash值'  #显示对象大小

git checkout 命令

git checkout '分支名字' # 切换分支
git checkout -b '分支名字' # 基于当前的commit创建并切换分支
git checkout 'commit的hash值' -b '分支名字'   # 基于某个commit创建分支
git checkout -b '本地要创建的分支' '远端存在的分支' # 本地创建和远端一样的一个分支
git check -- '需要恢复的文件名'  # 恢复工作区和暂存区一样
git check # 显示工作区和暂存区不一样的文件

git commit 命令

git commit -m'提交说明' # 添加到版本历史 -m是可选的,用来提交说明
git commit -am'提交说明' # 相当于是add和commit的组合
git commit --amend #修改所在分支最近一次commit的message

git diff 命令

命令用于显示提交和工作树等之间的更改。此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。

git diff 'hash值' 'hash值' #比较两个对象之间的不同
git diff HEAD HEAD~1 #比较HEAD指代的commit和HEAD的父级,~也可以用^代替,HEAD^1^1代表HEAD的父级的父级,等同于head^^,也等同于head~2
git diff --cached # 比较暂存区和HEAD文件
git diff --staged # staged和cached一样,都是指暂存区
git diff # 默认比较工作区和暂存区的区别(比较所有文件)
git diff -- '文件名' # 比较工作区和暂存区指定文件的差异
git diff 'commit版本号' 'commit版本号' -- '文件名' # 比较两个commit之间同个文件的差异

git fetch

git fetch '远端站点名' # 站点是连接远端时候自己设定的,默认是origin,fetch远端到本地
git fetch '远端站点名' '分支名' # 指定拉取远端的某个分支

git help 命令

git help --web log #查看log所有参数

git log 命令

git log #查看所有版本历史
git log -all #查看所有分支版本历史
git log --all --graph #图形化分支版本历史
git log --oneline #查看所有版本历史(简单,顾名思义每个版本一行信息)
git log -n #查看最近的n个版本历史
git log -n --oneline #查看最近的n个版本历史(每个版本单独一行显示)

git pull 命令

git pull # 相当于执行了fetch和merge两个指令

git push 命令

git push '站点名' --all # 把本地仓库所有文件传输要远端

git rebase 命令

git rebase -i '要修改的commit的父commit的hash值' #可用来修改message和合并commit

git reset 命令

git reset --hard #清除暂存区和工作区所有的变更(谨慎操作)
git reset --hard HEAD~1 #版本回退一级并清除暂存区
git reset HEAD # 恢复暂存区和HEAD一样
git reset HEAD -- '文件名'  #恢复指定文件和HEAD一样
git reset --hard HEAD # 此命令执行后工作区、暂存区和HEAD文件一样

git status 命令

git status #查看当前git管理区状态




git cat-file -t
ls -al #查看当前目录下所有文件包括隐藏的,去掉 -al 即查看非隐藏文件
cd 文件夹名字 #进入文件夹
cd / #退到根目录
cd .. #退到上一级目录
vi 文件名字 #进入文件的编辑状态
cp '文件路径+文件名字' '重置的文件名.格式' #复制文件到当前目录并重新指定名字及格式
cp '文件路径+文件名字' . # 复制文件到当前目录(注意是.不是句号)
cp -r '文件夹路径+文件夹名字' '重置的文件夹名字' #复制文件夹到当前目录并更改文件夹名字
cp -r '文件夹路径+文件夹名字' . # 复制文件夹到当前目录
mkdir 文件夹名字 #创建文件夹
mv '文件名+格式' '文件名+格式' #文件重命名(方式不止一种)
echo "hello,world" >readme 创建一个文件名是readme包含内容是"hello,world"的readme文件
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值