Git
hash–SHA
git文件管理机制:文件系统的一组组快照,每次提交都会对当前的全部文件制作一快照并保存这个快照的索引。
提交对象及其父对象形成链条, 切换分支和创建分支都是关于指针的操作
git初始项目配置
系统配置:/etc/gitconfig
全局配置:~/.gitconfig
项目配置:工作区/.git/config
git config –list
命令列出Git可以在该处找到的所有的设置
git配置全局
- 通过命令行去设置用户名和邮箱
git config --global user.name "Firstname Lastname"
git config --global user.email "your_email@email.com"
- 找到对应的.gitconfig文件
[user]
name = Firstname Lastname
email = your_email@email.com
- 如果是首次配置,且是新申请的git账户,还需要配置ssh key
运行命令创建SSH Keys:ssh-keygen -t rsa -C "your_email@email.com"
输入密码等一系列信息结束后的结果:
Your identification has been saved in /home/peko/.ssh/id_rsa. #私有密钥
Your public key has been saved in /home/peko/.ssh/id_rsa.pub. #公开密钥
The key fingerprint is:
SHA256:rYpYFp/gnaWz/V1YWMFV0sWemPA/W8KSjuIHruBMLqI your_email@email.com
The key's randomart image is:
+---[RSA 2048]----+
| .o+*|
| . .oo|
+----[SHA256]-----+
添加公开密钥:到平台gitlab等上面添加ssh 公钥
标题栏中输入适当的密钥名称,用Company即可;Key则需要将刚才生成的公共密钥内容复制进去
查看id_rsa.pub文件中的内容cat ~/.ssh/id_rsa.pub
将ssh-ras 密钥内容 your_email@email.com的内容全部复制到Key中
单击确定按钮完成添加
4.进行认证:ssh -T git@gitee.com
执行按问题完成输入后,网站提示成功信息
git 单独的项目配置
日常使用git时,一般会有全局配置文件的.gitconfig,所有项目会默认使用这个配置。如果需要特殊配置某个项目,只需要修改项目里的.git/config文件即可。但如果需要修改项目数量变多就容易忘,导致提交错误author的commit。
比如: 公司项目与个人项目,想使用不同的user.name与user.email,简单操作就是,修改个人项目中.git/config中的配置【同git全局配置1,2】
方法1:
git config user.name name1
git config user.email name1@example.com
方法2:
[user]
name = name1
email = name1@example.com
这样就会覆盖全局配置,但项目一多,这种方法就显得效率很低。
git设置某一个目录下
个人会用不同的文件夹区分公司与个人的项目集,这样就可以通过git conditional include,给不同目录下的项目,设置不同的git config。
假设公司项目,会放在work目录下。
- 新建一个.gitconfig-work,内容如下
[user]
name = name2
email = name2@example.com
- 打开全局配置.gitconfig文件,添加目录配置
[includeIf "gitdir:~/work/"]
path = .gitconfig-work
这样work下的新项目,都会使用.gitconfig-work中的配置覆盖全局配置,从而达到不同目录使用不同的git config
对于work目录下已存在的项目,可执行以下命令查看.gitconfig-work中配置是否生效
git config --show-origin --get user.name
git config --show-origin --get xxxx
git 命令
- git stash : 缓冲区
1.git stash save "message"
/git stash save -a "message"(慎用)
2.git stash pop [ stash@{id} ]
/git stash apply [ stash@{id} ]
apply不删除缓存里的,pop删除即弹出来了就不存在了
3.git stash list 看哪个文件不同
4.git stash show 看文件diff不同
5.git stash clean 清除缓冲区
git stash save -a "message"
慎用–它会把gitignore里的东西都放进去!!!切回来的时候,告诉你xxx already exists, no checkout Could not restore untracked files from stash
解决办法:
1.把项目里exists的东西删除掉,用git clean -f / git clean -fdx命令,基本上都是.gitignore里的东西。删完就好了
2.接下来,可以用:git stash pop stash@{id}命令来进行恢复了
-
git status : 工作区、暂存区的状态
信息: on branch 分支;没有任何提交(本地仓库为空);没有啥可提交(暂存区为空);
git rm --cached file.txt
将file.txt移除暂存区 -
git add : 添加
将工作区的新建和修改添加到暂存区 -
git commit -m “” [filename]
将暂存区内容提交到本地库 -
git commit --amend
:- 如果commit注释写错了,只是想改一下注释。
- 此时会进入默认vim编辑器,修改注释完毕后保存就好了。
- 也可以直接命令行
git commit --amend -m 'new commit message'
- 修改最后一次提交
直接输入命令:git commit --amend,会进入对最后一次提交信息编辑的vim编辑器界面(普通模式下,按i进入编辑模式,编辑模式下按esc退出到普通模式,普通模式下按:进入命令模式,输入wq即可保存修改并退出vim编辑器)。 - 修改某一次提交
git rebase -i 32e0a87f
- 在跳出来的 VI 中将要修改的提交状态从 pick 改为 edit,然后保存并退出vim。此时已经到了要修改的提交id下
- 修改完代码后提交:
git commit --amend
git rebase --continue
- 如果commit注释写错了,只是想改一下注释。
-
git log 查看提交历史记录
git log
HEAD指针指向当前版本
参数 --pretty=oneline 或者 --oneline(显示hash一部分)
信息:hash索引 commit-message
git log --oneline
选项来查看历史记录的简洁的版本
git log --graph
开启了拓扑图选项
git log --reverse
参数来逆向显示所有日志
git log --author
指定用户的提交日志
指定日期,可以执行几个选项:–since 和 --before,但是你也可以用 --until 和 --after
git blame <file>
查看指定文件的修改记录 -
git reflog
记录HEAD指针的每次移动(例如,每次提交、合并、rebase、cherry-pick、reset等)。Git会将操作记录在Reflog中,使它成为一个有价值的日志
信息: 部分hash HEAD@{1}: commit: message
{number}表示回到这一版本需要的步数
设置reflog过期时间: 过期时间更改为180天:git config gc.reflogExpire 180.days.ago
可以设置Reflog永不过期git config gc.reflogExpire never
技术上来说,这个本地记录不是代码库的一部分,它与提交分开存储。Reflog是.git/logs/refs/heads/中的一个文件,用来跟踪每个分支的本地提交。Git的日志通常会在90天后被清理(这是默认设置),但是可以轻松调整Reflog的过期日期。
Git区分了代码库的配置文件(.git /config)、每个用户的全局配置($HOME/.gitconfig)和系统全局设置(/etc/gitconfig)。要为用户或系统调整Reflog的过期时间,请在上面所示的命令后面添加–system或–global参数。
- 版本前进后退 reset
基于索引值:git reset --hard hash(索引)
【为需要撤销的commit的提交的前面一个提交的版本,即需要恢复到的提交的id,重置至指定版本的提交,达到撤销提交的目的】
使用^符号:只能后退git reset --hard HEAD^(后退一步,几个^就几步)
使用~符号:只能后退git reset --hard HEAD~n
(后退n步)
参数:
–hard: 在本地库移动指针,充值暂存区,重置工作区
–mixed: 在本地库移动指针,重置暂存区
–soft: 仅仅在本地库移动指针
git reset : git commit之后,想撤销commit,未push
git reset --soft
就成功的撤销了你的commit,仅仅是撤回commit操作,您写的代码仍然保留。
--mixed
:不删除工作空间改动代码,撤销commit,并且撤销git add . 操作。这个为默认参数,git reset --mixed HEAD^
和git reset HEAD^
效果是一样的。
--soft
:不删除工作空间改动代码,撤销commit,不撤销git add .
--hard
:删除工作空间改动代码,撤销commit,撤销git add . 。注意完成这个操作后,就恢复到了上一次的commit状态。
git reset HEAD^ a.py
:回退a.py这个文件的版本到上一个版本
git reset –hard origin/master
:将本地的状态回退到和远程的一样
-
删除文件找回
git reset --hard 指定版本
永久删除文件后找回(commit操作以后)
添加到暂存区的删除文件找回(add操作以后) -
比较文件
git diff file
:将工作区中的文件和暂存区进行比较
提交到暂存区比较: git diff HEAD 表示跟本地库中的版本比较
不带文件名比较所有文件 -
分支
- git branch -v 查看所有分支
- git branch 分支名 创建分支
- git checkout 分支名 切换分支
- git branch -r 查看所有远程分支
- git branch -a 查看本地分支
- 拉取远程分支并创建本地分支:
- git checkout -b 本地分支名x origin/远程分支名x
使用该方式会在本地新建分支x,并自动切换到该本地分支x。
采用此种方法建立的本地分支会和远程分支建立映射关系。 - git fetch origin 远程分支名x:本地分支名x
使用该方式会在本地新建分支x,但是不会自动切换到该本地分支x,需要手动checkout。
采用此种方法建立的本地分支不会和远程分支建立映射关系。
- 合并分支:切换到接收修改的分支 执行git merge 修改的分支
冲突:同时对同一位置做了修改
<<<<当前分支
====另一分支
解决冲突:编辑文件,删除特殊符号,之后提交到本地库 - 分支重命名
- 本地分支重命名
git branch -m 原始名称 新名称
例如 修改 test 为 newTestgit branch -m test newTest
- 远程分支重命名
1.先重命名本地分支
git branch -m 旧分支名称 新分支名称
2.删除远程分支
git push --delete origin 旧分支名称
3.上传新修改名称的本地分支
git push origin 新分支名称
4.修改后的本地分支关联远程分支
git branch --set-upstream-to origin/新分支名称
注意:本地分支和远程分支建立映射关系的作用
建立本地分支与远程分支的映射关系(或者为跟踪关系track):这样使用git pull或者git push时就不必每次都要指定从远程的哪个分支拉取合并和推送到远程的哪个分支了。
git branch -vv
上面的本地分支和远程分支都有映射关系,如果没有,就需要手动建立
git branch -u origin/分支名
或者
git branch --set-upstream-to origin/分支名
origin 为git地址的标志,可以建立当前分支与远程分支的映射关系。撤销本地分支与远程分支的映射关系
git branch --unset-upstream
之后可以再次用git branch -vv 查看本地分支和远程分支映射关系
cherry-pick
将代码从一个分支转移到另一个分支
需要将某一个分支的所有代码变动,那么就采用合并(git merge)
只需要某一个分支的部分代码变动(某几个提交),这时可以采用 Cherry pick
复制提交
git cherry-pick <commitHash>
【提交的commitHash应用于当前分支。此时在当前分支产生一个新的提交,新提交代码的哈希值会和之前的不一样。】
git cherry-pick feature
分支名,表示转移该分支的最新提交【将feature分支的最近一次提交,转移到当前分支】
支持一次转移多个提交
git cherry-pick <HashA> <HashB>
git cherry-pick A..B
【转移从 A 到 B 的所有提交。它们必须按照正确的顺序放置:提交 A 必须早于提交 B,否则命令将失败,但不会报错。提交 A 将不会包含在 Cherry pick 】
git cherry-pick A^..B
【同上一条,但要包含提交 A】
代码冲突
如果操作过程中发生代码冲突,Cherry pick 会停下来,让用户决定如何继续操作。
–continue
用户解决代码冲突后,第一步将修改的文件重新加入暂存区(git add .),第二步使用下面的命令,让 Cherry pick 过程继续执行。
git cherry-pick --continue
–abort
发生代码冲突后,放弃合并,回到操作前的样子。
–quit
发生代码冲突后,退出 Cherry pick,但是不回到操作前的样子。
-
远程
- git remote add origin url 在本地创建远程库地址别名
- git push origin master 推送master分支到origin地址
加入项目前 - git clone url 克隆远程库到本地(all in)
完整的下载远程库到本地
创建origin远程地址别名
初始化本地库
邀请进入项目
settings->collaborators->add ->accept(接受后获得项目权限) - pull = fetch + merge
git pull origin master
读操作:git fetch origin master 抓取操作——fetch只是抓取远程的内容,但没有更改本地工作区的文件
git merge origin/master 将远程的master合并到本地master - 本地切换远程库分支 git checkout origin/master
- 冲突:如果不是基于github远程库的最新版本所作的修改,不能推送,必须先拉取;拉取下来后如果进入冲突状态,则按照分支冲突解决。
- 查看当前项目关联的远程仓库地址
git remote -v
添加远程别名git remote add <远程地址别名--origin> https:……/仓库.git
删除远程别名git remote remove origin
: - 删除远程分支:
git push origin --delete <branchName>
- 强制提交到当前版本号
git push origin 分支名称 --force
-
跨团队协作
- fork, 访问别人项目的git仓库后点击fork——以自己的身份;结果是有了一个和别人一模一样的自己的远程仓库。
- clone下来做修改后提交到本地库, push到自己的远程仓库
- 发起pull-request
- 别人confirm merge 后拉取到本地
-
SSH
- ssh-keygen -t rsa -C url
- 本地复制id_rsa.pub 的内容到github上添加sshKey
- git remote add origin_ssh <ssh地址>
-
gitconfig 自定义命令:
您有一个别名,默认情况下会在您的 .gitconfig 中添加此项,每次推送或提交时都会传递此标志。
.gitconfig
向您的 git 配置添加别名(即强制提交的 fcommit)将每次都应用 --no-verify。
[alias]
fcommit = commit --no-verify
使用
git fcommit
git使用过程遇到的一些问题
运行ssh -T git@github.com
出现 ssh: connect to host github.com port 22: Connection timed out
运行 git push origin master
出现 fatal: unable to access 'https://github.com/../': Failed to connect to github.com port 443: Timed out
网络上有一些碰到这个问题的解决方式,但是我的进行相关设置没有用,隔天就正常了,似乎和github有关。
运行git pull
出现 You have divergent branches and need to specify how to reconcile them.
这是由于你拉取pull分支前,进行过merge合并更新分支操作,导致版本不一致
-
第一种解决方法:
执行git config pull.rebase false
默认将pull下来的代码与现有改动的代码进行合并
但是可能会造成代码冲突,需要处理下这个问题 -
第二种解决方法:回退到合并之前的代码,在进行pull拉取最新代码
git常用操作
- 本地提交记录删除
删除本地提交记录的最后一条或最后N条记录
git reset --hard HEAD~1
删除提交记录中的某几条
- 使用命令查看提交的记录: git log
- 找到相应的记录ID
- 执行命令:git rebase -i 记录ID
- 进入到一个页面。
- 使用cw命令将行首的pick替换为drop(注意每完成一个替换操作,需要按下Esc键退出vi的编辑模式)。
- 检查确认后,按wq保存并退出
-
强制提交到远程
git push -f
-
拉取远程非当前分支到本地分支
git fetch origin master
git merge origin/master
-
查看某个文件历史提交信息
git log relativePath
查看某个文件的commit记录
git log -p relativePath
查看文件每次提交的diff
提交规范
提交描述
Commit message 的格式
每次提交,Commit message 都包括三个部分:Header,Body 和 Footer。
<type>(<scope>): <subject>
// 空一行
<body>
// 空一行
<footer>
其中,Header 是必需的,Body 和 Footer 可以省略。
不管是哪一个部分,任何一行都不得超过72个字符(或100个字符)。这是为了避免自动换行影响美观。
Header部分只有一行,包括三个字段:type(必需)、scope(可选)和subject(必需)。
(1)type: type用于说明 commit 的类别,只允许使用下面7个标识。
- feat:新功能(feature)
- fix:修补bug docs:文档(documentation)
- style:格式(不影响代码运行的变动)
- refactor:重构(即不是新增功能,也不是修改bug的代码变动)
- test:增加测试
- chore:构建过程或辅助工具的变动
如果type为feat和fix,则该 commit 将肯定出现在 Change log 之中。其他情况(docs、chore、style、refactor、test)由你决定,要不要放入 Change log,建议是不要。
(2)scope
scope用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。
(3)subject
subject是 commit 目的的简短描述,不超过50个字符。
Body 部分是对本次 commit 的详细描述,可以分成多行。
Footer 部分只用于两种情况。
(1)不兼容变动
(2)关闭 Issue
如果当前 commit 用于撤销以前的 commit,则必须以revert:开头,后面跟着被撤销 Commit 的 Header。
配置
钩子脚本代码命名为commit-msg 命令行执行文件,放到项目的.git->hooks下面,
脚本
工具
commitizen 添加带提示的 commit 编辑
- 安装
npm i --save-dev commitizen
- 在 package.json 添加一个 script 命令配置:
"scripts": {···"commit": "cz"···
},
- commitizen 只是一个基础,还需要安装 @commitlint/cz-commitlint 才能使用
npm install --save-dev @commitlint/cz-commitlint
- package.json 添加相关 config 配置:
···
"config": {"commitizen": {"path": "@commitlint/cz-commitlint"}
}
···
- 执行 npm run commit ,是否会弹出一个命令行交互,如果正常,则安装成功。
按提示完成交互后,会自动帮你执行 git commit -m ‘xxx’ 提交,提交的时候,又会触发 husky 的 hook 进行格式校验,校验通过后正常提交 commit 。
github的提交设置
- github的提交设置
分支保护:GitHub允许你设置分支保护规则,以确保只有满足特定条件的提交才能被合并到受保护的分支中。你可以设置需要进行代码审查、通过特定的CI/CD流程、通过特定的测试等条件来限制提交。
强制代码审查:你可以配置GitHub使得所有的提交都需要经过代码审查才能被合并。这可以确保团队中的其他成员对代码进行审查并提供反馈。
强制签名提交:GitHub支持使用GPG密钥对提交进行签名。你可以配置GitHub要求所有提交都必须经过签名,以确保提交的真实性和完整性。
限制提交者:你可以配置GitHub只允许特定的用户或团队提交代码。这对于限制代码的提交范围和确保代码质量非常有用。
限制提交时间:你可以设置提交时间窗口,只允许在特定的时间段内提交代码。这对于控制代码的发布和维护时间非常有用。
限制提交大小:你可以设置最大提交大小,以防止大型文件或不必要的更改被提交到代码库中。