git各命令的原理和初级使用,顺手玩下git钩子

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: git各命令的原理和初级使用,顺手玩下git钩子

git各命令的原理和初级使用,顺手玩下git钩子


该文章是在阅读猴子也懂的git入门抛物线大神的git原理和使用小册子,额,需要一点点零花钱之后总结的,估摸着不适合新手...

TL;DR

  • 核心概念:暂存区(索引),数据库(repository)是每个commit组成的,HEAD/branch/tag都指向某个commit
  • 远程仓库实际上和本地仓库没啥不同,纯粹为了7x24小时开机并交换大家的修改。
  • 没事常常git statusgit lg,没写错,配置git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit",炒鸡炫酷
  • 需要在git执行某条命令的时候执行脚本,就用到钩子
  • 搭建远程仓库

git概念理解

  • 没有git的时候,想要保存文件的状态只能备份备份再备份,如果放到服务器上指不定还被谁不小心的覆盖了。用git管理文件的时候,更新的历史会保存在git里,也不会轻易被覆盖。
  • 文件更新的历史保存git的数据库(repository)。有本地的数据库还有远程数据库,可以自己新建,也可以复制远程的。
  • 若要把文件或目录的添加和变更保存到数据库,就需要进行提交,执行提交后,数据库中会生成上次提交的状态与当前状态的差异记录(也被称为revision),系统根据修改的内容计算出40位数字和英文生成版本号,俗称某个commit或者某个版本
  • 实际操作的目录称为工作树(working tree),在数据库和工作树之间有索引,索引是为了向数据库提交做准备的区域。没有索引的文件是不能提交到数据库的~。索引很多时候又被称为stage,暂存区。工作树的内容跟着HEAD走。一旦HEAD指向新的版本,工作树的内容也会变成那个版本,形同备份~
  • branch、tag、HEAD都是某个版本的引用,可以想象,数据库是一条横着的线,每次提交就是一个点,每个点有自己的id,点上面可能有branch、tag、HEAD这几个指向

git命令的本质

  • git clone url [projectName]复制url的远程数据库到本地,git会将这个远程数据库命名为origin,projectName可选,省略的话文件夹名字同远程数据库的,写的话就重命名。这里HEAD指向master分支的最新的版本,自然工作区也跟着HEAD。
  • git add file/.,将工作树的某些文件创建索引的,.表示所有文件,注意,add添加的不是文件名字,而是文件改动的内容。新文件必须通过这个才让git追踪这个文件。不然git不知道该文件的存在。
  • git commit -m"认真写改了啥",将索引添加到本地数据库,可以想象成横线多了一个点,又长了些。HEAD自动更新到新的commit,且HEAD会拖着当前的分支,让其也指向新的commit。
  • git pull [origin] [master],将远程数据库的某个分支的内容更新到本地数据库的相应分支,pull 的内部操作其实是把远程仓库取到本地后(使用的是 fetch),再用一次 merge 来把远端仓库的新 commits 合并到本地。后面两项是指哪个远程仓库的哪个分支,省略的话是origin,然后当前目录所在的分支。这里注意,执行这个操作的时候,可能远程数据库和本地数据库合并的时候,有冲突,解决掉就好,然后git add .;git commit本地的数据库从分叉的地方开始插入到远程数据库里更新的后面,有冲突的话将会生成多生成一个commit。可以git log看看
  • git push [origin] [master],将本地的数据库添加到远程数据库哪个分支,如果总是想省略(我是省略重度依赖者。。),git config --global push.default current,这样是处在哪个分支就会更新origin的哪个分支。如果实在master分支,这个操作会让origin/HEAD,origin/master指向最新的commit,也就是远程仓库的HEAD和master指针。
  • git checkout [-b] branch,将 HEAD 指向branch ,工作目录的文件内容跟着HEAD,变成这个版本的内容 ,俗称切换分支,当然后面的参数可以是任意的commitID,需要注意的是,当前目录所在分支尽量clean,如果有需要提交的可能会切换失败,如果切换成功,默认为在新的分支下做了这些变更。-b一般是创建新分支且切换到新分支的意思。
  • git stash -u,暂存当前分支的改动,工作区恢复到最新的commit版本,一般常用于紧急切换分支,又不想盲目提交commit,想要恢复改动的内容git stash pop-u是将新建的文件一并暂存。
  • git merge branch,从目标 commit 和当前 commit (即 HEAD 所指向的 commit)分叉的位置起,把目标 commit 的路径上的所有 commit 的内容一并应用到当前 commit,然后自动生成一个新的 commit。merge会自动合并,如果同一个文件上修改可能会合并失败,解决完冲突之后git add 文件;git commit就可以了。放弃merge的话git merget --abort,merge后面可以是branch,也可以是一般的commit。是不是感觉和pull很像,当然!!!pull就是fetch和merge的合体~~~

git branch [newbranch] [-d]省略后面的,会显示所有分支,加上后面的表示创建分支,删除分支的话-d,强制删除-D

git tag tagName,tag 是一个和 branch 非常相似的概念,它和 branch 最大的区别是:tag 不能移动。所以在很多团队中,tag 被用来在关键版本处打标记用。多用在master分支上。

git revert commitId,将某commit取反,也就是放弃某次的修改,这个命令会生成新的commit。

git reset commitId --hard,将HEAD以及当前的branch指向移动到目commit,工作区的内容随着HEAD一起变化,有时候想丢弃某些commits用这个命令。经常用这个git reset HEAD --hard放弃本地所有的修改,恢复到上一次的commit状态。

git remote name url,添加一个远程数据库,并且起一个名字,感觉用的不多

git的查找和配置

git log,查看日志,git log --patch查看详细的日志,git log --stat查看简要的日志,想要切回到某个版本的时候会用到

git show [commitID] [某文件],看某一个版本的日志。省略commit表示当前的commit,省略某文件表示所有文件。

git diff commitID,将工作区的内容和目标commit做一个对比。

git status,查看当前的状态,随时会用

git config,对git的一系列配置。属于「一次付出,终身受用」的高性价比内容。global参数针对全局git,不加那只针对当前的仓库起作用。全局配置在用户主目录下的一个隐藏文件~/.gitconfig中,本地配置在仓库根目录的.git/config。查看配置git config --global --list。以下是常用的配置: 比如配置别名,git config --global alias.co checkout;git config --global alias.ci commit;git config --global alias.br branch也就是可以git co xxbranch;git ci -m"xx";git br
比如配置不容易的命令,git config --global alias.unstage 'reset HEAD'下次git unstage file就表示将暂存区的修改撤销掉,回到工作树那边。git config --global alias.back 'reset HEAD --hard'git back表示放弃所有修改,工作区返回到上一次的commit。git config --global alias.last 'log -1'显示最后一次提交的信息。git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"嘿嘿,这样可以git lg显示日志,特别好用!!!强烈推荐!!!
比如上面配置push。

分支的应用

公司中多数是这样开发的:

master分支一般只管理发布状态,在提交的时候使用标签记录发布版本号

develop分支是发布的日常开发分支

任何新的功能(feature)或 bug 修复全都新建一个 branch 来写,新分支可能feature-xxx,hotfix-xxx,feature表示功能开发,hotfix发布的产品有紧急bug,修改完之后合并

branch 写完后,合并到 master,然后删掉这个 branch。当然也可以借助pull requests

HEAD、master与branch

每个commit就是每个版本,每个记录的意思。称呼不一样。

git log执行后,一般第一行的 commit 后面括号里的 HEAD -> master, origin/master, origin/HEAD,是几个指向这个 commit 的引用。

在 Git 的使用中,经常会需要对指定的 commit 进行操作。每一个 commit 都有一个它唯一的指定方式也就是上图中每个黄色的 commit 右边的那一长串字符。两个 SHA-1 值的重复概率极低,所以你可以使用这个 SHA-1 值来指代 commit,也可以只使用它的前几位来指代它(例如第一个 78bb0ab7d541…16b77,你使用 78bb0ab 甚至 78bb 来指代它通常也可以),

但毕竟这种没有任何含义的字符串是很难记忆的,所以 Git 提供了「引用」的机制:使用固定的字符串作为引用,指向某个 commit,作为操作 commit 时的快捷方式。

HEAD

HEAD 是 Git 中一个独特的引用,它是唯一的。

HEAD是当前工作目录所对应的commit。

当有新的commit的时候(commit或者pull的时候),工作目录会与最新的commit对应,HEAD也就指向最新的commit。

当使用checkout、reset等指令手动改变工作目录的commit时,HEAD也会跟过去

当前目录的commit在哪,HEAD就在哪,永远指向当前目录的commit,也就是可以用HEAD操作当前目录的commit

branch

Git 还有一种引用,叫做 branch(分支)

HEAD 除了可以指向 commit,还可以指向一个 branch,当它指向某个 branch 的时候,会通过这个 branch 来间接地指向某个 commit;另外,当 HEAD 在提交时自动向前移动的时候,它会像一个拖钩一样带着它所指向的 branch 一起移动。


  • branch可以理解为是指向commit的一个引用,也可以理解为从第一个commit到branch指向的commit之间所有的commits的一个串

master

  • 默认的branch,创建新仓库的时候,第一条commit创建,master会指向它,HEAD指向master
  • git clone的时候,除了从远程仓库把 .git 这个仓库目录下载到工作目录中,还会 checkout (签出) master(checkout 的意思就是把某个 commit 作为当前 commit,把 HEAD 移动过去,并把工作目录的文件内容替换成这个 commit 所对应的内容)。


  • origin/HEAD,origin/master是远程仓库的镜像引用

「引用」的本质

所谓「引用」(reference),其实就是一个个的字符串。这个字符串可以是一个 commit 的 SHA-1 码(例:c08de9a4d8771144cd23986f9f76c4ed729e69b0),也可以是一个 branch(例:ref: refs/heads/feature3)。

Git 中的 HEAD 和每一个 branch 以及其他的引用,都是以文本文件的形式存储在本地仓库 .git 目录中,而 Git 在工作的时候,就是通过这些文本文件的内容来判断这些所谓的「引用」是指向谁的。

git的高级(难一点)的命令

这部分不具体写命令了,如果有需求,再进行查阅吧。

rebase的意思是,给你的 commit 序列重新设置基础点(也就是父 commit)。展开来说就是,从目标 commit 和当前 commit (即 HEAD 所指向的 commit)分叉的位置起,以目标 commit 为基础,依次重新提交分叉之后所有 commit 的内容,这话听着别扭,就是把当前所在分支的分叉的所有commits,都复制一份放在参数branch后面

指定amend选项执行提交的话,可以修改所在分支最新的提交,git add 笑声.txt;git commit --amend,其实相当于这次的提交直接覆盖掉上次的提交。

在cherry-pick,您可以从其他分支复制指定的提交,然后导入到现在的分支。

在rebase指定i选项,您可以改写、替换、删除或合并提交。

merge的特殊选项:squash,用这个选项指定分支的合并,就可以把所有汇合的提交添加到分支上。

示例

# 查看状态
git status
# 添加索引
git add file
# 添加数据库,将HEAD自动更新到新的commit,且HEAD会拖着当前的分支,让其也指向新的commit
git commit -m"msg"
# 将远程数据库的内容更新到本地数据库,默认的远程数据库和分支名字是 origin master
git pull origin master
# 将本地数据库添加到远程数据库。你用不加参数的 git push 只能上传那些之前从远端 clone 下来或者 pull 下来的分支,而如果需要 push 你本地的自己创建的分支,则需要手动指定目标仓库和目标分支(并且目标分支的名称必须和本地分支完全相同),就像上面这样。所有分支都可以用 git push 来直接 push,目标自动指向 origin 仓库的同名分支,通过 git config 指令来设置 push.default 的值为:current
git push origin master
# 添加远程数据库并且将远程数据库起个名字,一般起origin
git remote origin http://xxxxx
# 复制远程数据库,默认的新目录的名字同项目名,git会将这个地址命名为origin
git clone http://xxxx projectName
# 查看数据库
git log
# 切换到某一版本,或者分支
git checkout xxxx
# 需要暂存修改,stash是临时保存文件修改内容的区域
git stash
# 释放
git stash pop
# 查看分支
git branch
# 创建分支 hotfix- feature- release- develop master,其实只是将当前commit创建了一个引用,HEAD指针并没有指向新分支,如果需要,git checkout xxx
git branch xxx
# 创建并切换到新分支,创建新引用,且将HEAD指向这个新引用
git checkout -b xxx
# 删除分支,所谓的删除,只是删除这个commit的引用,可以从git log那找到这个commit,未合并到master的分支会删除失败,但可以强制删除,-d改成-D
git branch -d xxx
# issue1分支需要合并到master上,rebase的历史记录更少
# merge
git checkout master;git pull;git merge issue1;
# rebase
git checkout issue1;git pull;git rebase master;git checkout master;git merge issue1
# 查看标签,想要看注解加上 -n
git tag
# 打标签
git tag tagnamexxxx
# 打注解标签
git tag -am "注释信息" tagnamexxx
# 看包含标签的历史记录
git log --decorate
# 删除标签
git tag -d tagnamexxxx

git钩子的简单使用

一个新需求下来了,通常自己建个分支开始完成功能,等到完成的时候,自己测得也差不多了,就会合并到develop分支,然后部署到服务器,让测试来测。每次这样嫌费劲,就想着push到develop的时候,部署自动操作,这样省了很多麻烦吖。。。

这就用到钩子了,这边我没怎么研究,大约知道,就是在执行add commit push pull merge等操作的时候,可以在相应的时机执行相应的脚本。

项目根目录下.git/hooks下,有很多文件,去掉后缀.sample就可以在相应的时机执行这个脚本。脚本的语言,自己开心就好~~

本地仓库的钩子:

pre-commit: 执行git commit命令时触发,常用于检查代码风格

post-commit: 整个git commit完成后触发,常用于邮件通知、提醒

post-merge: 成功完成一次 merge行为后触发

pre-push: 执行git push命令时触发,可用于执行测试用例

pre-auto-gc: 执行垃圾回收前触发

prepare-commit-msg: commit message编辑器呼起前default commit message创建后触发,常用于生成默认的标准化的提交说明

commit-msg: 开发者编写完并确认commit message后触发,常用于校验提交说明是否标准

applypatch-msg: 执行git am命令时触发,常用于检查命令提取出来的提交信息是否符合特定格式

pre-applypatch: git am提取出补丁并应用于当前分支后,准备提交前触发,常用于执行测试用例或检查缓冲区代码

post-applypatch: git am提交后触发,常用于通知、或补丁邮件回复(此钩子不能停止git am过程)

pre-rebase: 执行git rebase命令时触发

post-rewrite: 执行会替换commit的命令时触发,比如git rebase或git commit --amend

post-checkout: 执行git checkout命令成功后触发,可用于生成特定文档,处理大二进制文件等

远程仓库用的钩子,一般我们就是要在服务端更新代码之后运行脚步,所以我们要修改的就是post-update或者post-receive。

pre-receive: 当服务端收到一个push操作请求时触发,可用于检测push的内容

update: 与pre-receive相似,但当一次push想更新多个分支时,pre-receive只执行一次,而此钩子会为每一分支都执行一次

post-receive: 当整个push操作完成时触发,常用于服务侧同步、通知

拿我为例,我用的,这里说下,最好是在服务器端执行git pull,但因为此项目是另外一个团队开发,我临时负责一个功能,也不知道服务器那边为啥不用git,我得到的信息是只能用复制替换

# .git/.hooks 新建pre-push
##!/bin/sh
# 拿到分支名
NAME=$(git branch | grep '*' | sed 's/* //')
echo "正在上传到服务器 $NAME"
# 在develop上push的时候主动将代码复制到服务器上面
if [ "$NAME" = "develop" ]
then
  scp  -r /Users/creen  root@10.2.2.156:/newoackend
fi

搭建git服务器

我觉得买服务器的时候,估计就用到,所以怕忘了,索性记一笔,大段引用廖雪峰大神的git教程。 远程仓库实际上和本地仓库没啥不同,纯粹为了7x24小时开机并交换大家的修改。GitHub就是一个免费托管开源代码的远程仓库。但一般公司需要自己搭建。

Ubuntu或Debian系统完成git安装需要以下几步:

# 安装git
sudo apt-get install git
# 创建一个git用户,用来运行git服务
sudo adduser git
# 创建证书登录,其实就是将所有需要登录的用户的id_rsa.pub文件,导入到服务器的/home/git/.ssh/authorized_keys文件里,一行一个。mac用户的公钥位置`~/.ssh/id_rsa.pub`
# 初始化Git仓库,先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令,Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾
cd /srv
sudo git init --bare sample.git
# 把owner改为git
sudo chown -R git:git sample.git
# 禁用shell登录,出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似git:x:1001:1001:,,,:/home/git:/bin/bash改为:git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell

git的用户可以在本地clone了

git clone git@server:/srv/sample.git

官方git文档

猴子也懂的git入门

抛物线大神的git原理和使用小册子,额,需要一点点零花钱

廖雪峰大神的git教程

巧用git钩子

imweb的git钩子,特别是可以用package.json指定钩子

拿到git分支的名字

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
26天前
|
开发工具 git
git 常用命令
这些只是 Git 命令的一部分,Git 还有许多其他命令和选项,可根据具体需求进行深入学习和使用。熟练掌握这些命令能够帮助你更高效地管理代码版本和协作开发。
|
18天前
|
机器学习/深度学习 Shell 网络安全
【Git】Git 命令参考手册
Git 命令参考手册的扩展部分,包含了从基础操作到高级功能的全面讲解。
26 3
|
1月前
|
缓存 Java Shell
[Git]入门及其常用命令
本文介绍了 Git 的基本概念和常用命令,包括配置、分支管理、日志查看、版本回退等。特别讲解了如何部分拉取代码、暂存代码、删除日志等特殊需求的操作。通过实例和图解,帮助读者更好地理解和使用 Git。文章强调了 Git 的细节和注意事项,适合初学者和有一定基础的开发者参考。
50 1
[Git]入门及其常用命令
|
2月前
|
开发工具 git
git学习四:常用命令总结,包括创建基本命令,分支操作,合并命令,压缩命令,回溯历史命令,拉取命令
这篇文章是关于Git常用命令的总结,包括初始化配置、基本提交、分支操作、合并、压缩历史、推送和拉取远程仓库等操作的详细说明。
141 1
git学习四:常用命令总结,包括创建基本命令,分支操作,合并命令,压缩命令,回溯历史命令,拉取命令
|
1月前
|
开发工具 git 开发者
|
1月前
|
开发工具 git 开发者
提升Git效率:掌握这5个高级命令
【10月更文挑战第17天】
62 0
|
3月前
|
存储 Linux 开发工具
掌握 Git 命令:每个开发者的必备技能
无论团队项目还是个人开发,掌握 Git 命令都是必备技能。本文介绍 Git 的基本概念与命令,如初始化仓库 (`git init`)、添加文件 (`git add`)、提交更改 (`git commit`)、检出分支 (`git checkout`)、合并分支 (`git merge`) 等,还分享了高级技巧如查看差异 (`git diff`)、撤销提交 (`git revert`)、修复合并冲突 (`git mergetool`) 和使用别名简化命令 (`git config --global alias.ci commit`)。
|
3月前
|
机器学习/深度学习 Shell 开发工具
Python使用管道执行git命令报错|4-7
Python使用管道执行git命令报错|4-7
|
3月前
|
存储 Linux 开发工具
Git基础命令,分支,标签的使用【快速入门Git】
本文详细介绍了Git版本控制系统的基础概念和常用命令,包括工作区、暂存区和版本库的区别,文件状态的变化,以及如何进行文件的添加、提交、查看状态、重命名、删除、查看提交历史、远程仓库操作和分支管理,还涉及了Git标签的创建和删除,旨在帮助读者快速入门Git。
Git基础命令,分支,标签的使用【快速入门Git】
|
3月前
|
开发工具 git
深入理解Git中的git pull和git fetch命令
深入理解Git中的git pull和git fetch命令
183 0