只有遇到问题,才会体会到技巧的好处!企业常用工作流主要介绍企业中常用的Git工作流!GitFlowMainBranchStableBranchDevelopmentBranchPatchBranchModificationBranchGithubFlowCreateBranchAddSubmission提交PRRequest讨论评估代码部署检测合并代码Git用法和方法要遵循!使用命令行代替图形界面使用命令行操作,简洁高效提交内容尽量表达提交修改内容区分主题和正文内容,使用空行分隔主题一般不超过50个字符每行主体控制的长度72个字符的主题的末尾无需使用句点或点。body是用来详细说明这个提交做了什么的。使用。开发方式不要直接在主分支上开发使用新分支开发功能和修复问题使用release分支和tag标记进行版本管理使用release分支发布代码和版本维护(release/1.32)使用tag标记版本(A-大特性功能。B-小特性功能。C-只修复bug)常用命令汇总整理,方便日常使用,记住6条命令即可。`#工作区->暂存区$gitadd暂存区->本地仓库$gitcommit-m"someinfo"本地仓库->远程仓库$gitpushoriginmaster#推送本地master分支到远程源仓库`#工作区<-暂存区$gitcheckout--#暂存区文件内容覆盖工作区文件内容#暂存区<-本地仓库$gitresetHEAD#本地仓库文件内容覆盖暂存区文件内容#本地仓库<-远程仓库$gitclone#克隆远程仓库$gitfetchupstreammaster#拉取远程代码到本地但不应用到当前分支$gitpullupstreammaster#拉取远程代码在本地但应用到当前分支$gitpull--rebaseupstreammaster#如果平时使用rebase合并代码,添加#工作区<-本地仓库$gitreset#本地仓库覆盖到工作区(保存回退文件内容修改)$gitreset--mixed#本地仓库覆盖到工作区(保存回滚文件内容修改)$gitreset--soft#本地仓库覆盖到工作区(保留更改)并添加到暂存区)$gitreset--hard#将本地仓库覆盖到工作区(删除不保留修改)配置实用程序参数选项虽然配置比较简单,但是非常有用!全局配置#用户信息$gitconfig--globaluser.name"your_name"$gitconfig--globaluser.email"your_email"#文本编辑器$gitconfig--globalcore.editor"nvim"#Pager$gitconfig--全球核心.pager"more"#别名$gitconfig--globalalias.gs"gitstatus"#纠错$gitconfig--globalhelp.autocorrect1个人配置#如果不加--global参数就是一个个人的配置$gitconfig--list$gitconfiguser.name$gitconfiguser.name"your_name"#如果在项目中设置,会保存在.git/config文件中$cat.git/config[user]name="your_name"......merge和rebase的选择什么时候用merge操作,什么时候用rebase操作?使用合并操作——Python中的Requests库供支持使用合并的开发人员使用。他们认为仓库的提交历史是对实际发生的事情的记录。这是一份历史文件。其实它本身就是有价值的,我们不应该随意修改我们的文字来改变历史,这无异于用“谎言”来掩盖实际发生的事情,这些痕迹应该保留下来。可能,这不是很好。#两个3rd分支的提交修改相同的内容*62a322d-(HEAD->master)Mergebranch'hotfix3'intomaster||*6fa8f4a-(hotfix3)hotfix3中的第三次提交*|548d681-master中的第3次提交|/*6ba4a08-第二次提交*22afcc1-使用rebase操作的第一次提交-支持使用rebase的开发人员使用Python中的Django库。他们认为提交历史是项目过程中发生的事情,项目的主干需要非常干净。但是,使用合并操作会生成一个合并的提交对象,这会在提交历史中增加一些非常冗余的内容。后面我们使用log命令查看提交历史的时候,会发现trunk的提交历史非常尴尬。比如同一个修改内容被提交了两次,很明显是分支合并导致的问题。#3rd的两个分支的commits修改相同的内容*697167e-(HEAD->master,hotfix)3rdcommit*6ba4a08-2ndcommit(2minutesago)*22afcc1-1stcommit(3minutesago)使用原理both的原则是只执行rebase操作,清理本地未推送或共享给他人的修改历史,绝不对已推送到仓库的commit记录执行rebase操作。这样,您就可以方便地享受到这两种方式带来的好处。更新仓库提交历史Git提供了一些工具可以帮助我们完善仓库中的提交内容,例如:mergemultiplecommit提交记录在日常开发中,我们为了完成一个功能或特性,会提交很多commit记录。但是最后,在提交PR之前,一般情况下,我们应该先整理一下这些提交记录。有些commit需要合并,或者需要删除等#调整最近5次提交记录$gitrebase-iHEAD~5$gitrebase-i5af4zd35#rewordc2aeb6e3rdcommitsquash25a3122之前第六次的commitvalue4thcommitpick5d36f1d5thcommitfixupbd5d32f6thcommitdrop571e96dHistory$gitlog*ce813eb-(HEAD->master)5thcommit*aa2f043-3rdcommit->modified*6c5418f-2ndcommit*c8f7dea-1stcommit删除意外调试的测试代码有一些历史记录有问题,但此时我们不想生成新的提交记录,到达修改后的目录。即修改之前的commit提交记录。#不使用pager$git--no-pagerlog--oneline-1d5e96d9(HEAD->master)sayfile#修改commit信息,添加到暂存区$echo"hello">say.txt$gitadd-u#更改当前最新提交记录$gitcommit--amend#更改并保留提交信息$gitcommit--amend--no-edit#更改当前最新提交记录并修改信息$gitcommit--amend-m"some_info"#Donotuseapager$git--no-pagerlog--oneline-19e1e0eb(HEAD->master)sayfile在多次提交中取消一些提交我们开发了一个函数,什么时候启动,产品经理说这个功能有些功能已经不需要了,就是相关功能的提交记录和内容可以忽略/删除。#回滚操作(回滚操作可以多次执行)#彻底提交上次的记录;也可以是PR#的提交记录默认会生成一个新的reverts类型的commit对象$gitrevert3zj5sldl[4]合并一些特定的commit我们不想合并整个分支,但是我们需要合并分支的一些提交记录。bash#cherry-pick$gitcherry-pick-xz562e23d使用reflogging我们如何取回丢失的内容和记录?之前我们说过,使用下面的命令回滚内容、强制推送代码、删除本地分支都是非常危险的操作,因为重置之后,我们是没有办法找到之前修改过的内容的。#回滚$gitreset--hard#推送$gitpushoriginmaster-f#分支$gitbranch-D其实Git给我们留了一个后门,就是利用relflog命令来检索之前的内容。只是比较麻烦而已。原理也很简单,就是当我们使用Git命令操作仓库时,Git会偷偷帮我们记录所有的操作。#查看日志记录$git--no-pagerlog--oneline-14bc8703(HEAD->master)hhhh#回滚到上次提交$gitreset--hardHEAD~1#查看参考日志记录$gitreflog6a89f1b(HEAD->master)HEAD@{0}:reset:movingtoHEAD~14bc8703HEAD@{1}:commit(amend):hhhh#获取内容$gitcherry-pick4bc8703批量修改历史提交虽然批量修改历史提交不常用,但是理解可以节省很多时间!我们之前学习的命令都是修改一个或多个commit提交信息的。如果我们需要全局修改历史提交怎么办?当然,Git也支持全局修改历史提交,比如全局修改邮箱地址,或者从全局历史中删除或修改一个文件。在开源项目中,公司邮箱用于提交提交的文件,其中包含私人密码相关信息。提交时,将大文件提交到仓库代码。这里我们可以使用filter-brach方法进行修改,但是建议在使用前新建一个。一个树枝,在上面测试没有问题之后,再在树干上操作,防止出问题,背上一个大锅。#创建分支$gitbranch-btesting#修改邮箱地址$gitfilter-branch--commit-filter'if["$GIT_AUTHOR_EMAIL"=="escape@escapelife.site"];然后GIT_AUTHOR_NAME="转义";GIT_AUTHOR_EMA"escape@gmail.com";gitcommit-tree"$@"elsegitcommit-tree"$@"fi'HEAD钩子函数的灵活使用主要介绍.git/hooks目录下的示例钩子函数!Git中有两种类型,分别对应客户端和服务端的钩子函数。执行提交和合并等操作时调用的客户端挂钩函数。服务端钩子函数是服务端收到代码提交后,可以启动代码检查和持续集成的一个步骤。作为开发者,我们并不知道如何搭建Git服务器,所以基本不会涉足。下面是Git自带的hook脚本,但是内置的hook脚本后缀为.sample,表示没有启用,是一个例子。如需启用,请删除后缀.sample。钩子脚本的相应内容是使用Shell语法编写的。?ll.git/hookstotal112-rwxr-xr-xapplypatch-msg.sample-rwxr-xr-xcommit-msg.sample-rwxr-xr-xfsmonitor-watchman.sample-rwxr-xr-x更新后。sample-rwxr-xr-xpre-applypatch.sample-rwxr-xr-xpre-commit.sample-rwxr-xr-xpre-merge-commit.sample-rwxr-xr-xpre-push.sample#不会PushcommitcontainingWIP-rwxr-xr-xpre-rebase.sample-rwxr-xr-xpre-receive.sample-rwxr-xr-xprepare-commit-msg.sample-rwxr-xr-xupdate.sample事实上,钩子脚本可以用任何语言编写,只要你让程序返回相应的退出代码即可。正常的代码集成流程是我们本地修改后提交PR请求并通过Github的CI检查,然后进行代码审查,最后合并到主干。但是,一个好的习惯是在代码提交之前保证代码不会出现语法错误等基本问题,比如通过flake8和PEP8标准。这时候我们可以使用pre-commit,一个Github的开源项目,它本质上是一个脚本,给项目添加了一个钩子函数,可以保证我们在提??交或者推送代码之前检查代码的质量。pre-commit-hooks项目包含了目前支持的钩子脚本,即一组开箱即用的钩子脚本。钩子脚本的相应内容是用Python语法写的。#安装方式$pipinstallpre-commit#指定钩子类型(即检查哪里)$pre-commitinstall-f--hook-typepre-push#配置需要执行的检查$cat.pre-commit-config.yamlrepos:-repo:https://github.com/pre-commit/pre-commit-hooksrev:v2.9.2hooks:-id:trailing-whitespace-id:flake8#检查$gitpushorigin推时掌握快克隆大型项目在大型项目中工作时,拉取代码会花费很多时间!如果我们要为Linux或者Python这样的大型项目做贡献,首先遇到的问题就是如何快速的将项目clone到本地。因为项目提交历史很多,仓库庞大,再加上国内网络的问题,当项目彻底拉下来的时候,我们的积极性可能会降低。幸运的是,Git也帮我们想到了这样的问题。我们可以通过--depth参数值拉取远程仓库上最新的提交历史,不包含项目历史,即.git/objects/目录下的对象只是本地的,不包含生成的对象通过之前的多次修改。#克隆不包含之前的历史$gitclonehttp://xxx.xx.xxx/xxx--depth=1但是有时候我们可能需要克隆仓库中某个标签版本对应的内容。如果我们直接使用clone命令无法做到,就需要进行如下操作才能完美解决。#克隆特定版本代码$gitinitxxx-15-0-1$gitremoteaddoriginhttp://xxx.xx.xxx/xxx$git-cprotocol.version=2fetchorigin15.0.1--depth=1$gitcheckoutFETCH_HEAD上面的效果基本可以满足我们的日常需求,但是很遗憾,你现在接了一个机器学习的项目,里面有大量的lfs文件,现在clone又会变得很慢。您可以使用以下操作来避免它。Git工具主动拉取lfs文件到达目录。#克隆不包含LFS数据$GIT_LFS_SKIP_SMUDGE=1gitclonehttp://xxx.xx.xxx/xxx如何处理工作中断如果是多路运行,还是可以高效开发的!比如我们目前在一个分支中给项目添加一个小功能。这个时候产品经理找到你,说线上环境有bug,需要你修复。但是,我们添加的小功能目前还没有完成。如果此时我们直接切换到主分支,那么之前的分支还没有来得及提交的所有内容都会被带到主分支。这是我们不想看到的情况。此时,我们需要保存之前分支的工作状态,等我们修改完线上的bug后再继续工作。幸运的是,Git也帮我们想到了这样的问题。我们可以使用stash子命令来帮助我们将当前工作区和暂存区的变化保存到栈中。需要处理的时候,弹出栈中的内容,我们再开发。?gitstash-husage:gitstashlist[]或:gitstashshow[][]或:gitstashdrop[-q|--quiet][]或:gitstash(pop|apply)[--index][-q|--quiet][]或:gitstashbranch[]或:gitstashclear或:gitstash[push[-p|--patch][-k|--[no-]keep-index][-q|--quiet][-u|--include-untracked][-a|--all][-m|--message][--pathspec-from-file=[--pathspec-file-nul]][--][...]]或者:gitstashsave[-p|--patch][-k|--[no-]keep-index][-q|--quiet][-u|--include-untracked][-a|--all][]#存储当前修改而不提交$gitstash#保存当前状态,包括未跟踪的文件$gitstash-u#显示所有存储信息$gitstashlist#返回存储状态$gitstashapply#删除存储区$gitstashdrop#回到上次stash的状态,删除本次stash信息$gitstashpop#删除所有stash信息$gitstashclear#fromsta在sh中取出某个文件的修改$gitcheckout--其实更安全的方式是将当前的修改全部push到远程仓库中。这样做的好处是,我们可以远程备份我们的修改,不用担心本地文件丢失等问题。当我们需要继续开发的时候,拉下相应的内容,然后想办法补救,比如使用--amend或者reset命令。#用最新的提交覆盖工作区和暂存区$gitcommit--amend$gitcommit--amend-m"some_info"#回退到指定版本并记录修改内容(--mixed)#覆盖本地仓库到工作区(保存回滚文件的内容修改)$gitreseta87f328$gitresetHEAD~$gitresetHEAD~2$gitreset~2$gitreset--mixed#本地仓库覆盖到工作区(删除不保留修改)$gitreset--soft#将本地仓库覆盖到工作区(保留修改并添加到暂存区)$gitreset--hard作者:Escape链接:https://www.escapelife.site/p...