鹤啸九天 自律更自由,平凡不平庸 Less is More

Git 学习笔记

2016-06-27
   
阅读量

Notes(温馨提示):

  1. ★ 首次阅读建议浏览:导航指南
  2. 右上角工具条搜索文章,右下角二维码关注微信公众号(鹤啸九天),底栏分享、赞赏、评论
  3. ★ 转载请注明文章来源,知识点积累起来不容易,水滴石穿,绳锯木断,谢谢理解
  4. ★ 如有疑问,邮件讨论,欢迎贡献优质资料


Git使用

总结

安装部署

git windows下载

VSCode

在线体验(解决访问受限问题)

【2021-2-10】用vscode在线查看github代码库,方法:

  • (1)加1s ,详见:github1s
  • (2)com→dev: VSCode福利来了,在github上面像本地一样开发
    • dev == 点击键盘上的 . 符号进入 web editor
    • 问题:【2021-8-17】没有push功能,修改的东西如何提交?是要付费才行吗?
  • github新功能,在线编辑IDE,codespace,Github 自从被微软收购后,和 vscode 的联动,真的是强强联手,从 GitHub Codespaces 和 GitHub Copilot 来看,好功能一个接一个

远程连接

使用VScode连接远程服务器进行开发

  • 直接在插件中搜索ssh,即可找到Remote-SSH,点击install安装
  • 左侧会出现一个远程资源管理的图标,选择SSH Targets,进入config配置文件
  • 可选:通过跳板机连接服务器
  • 点击SSH TARGETS下的服务器旁边的按钮纽行连接

配置文件

Host c00
    HostName xxx.xxx.xxx.xxx(跳板机IP)
    User lyfeng

Host c01
    HostName 192.168.0.10(内网地址)
    User lyfeng
    ProxyCommand "openssh的安装路径"\ssh.exe -W %h:%p -q c00
    # 连接c00, 再通过c00的局域网ssh到c01

基本概念

Git 工作区域

Git有四个工作区域:

  • 工作目录(Working Directory)
  • 暂存区(Stage/Index)
  • 资源库(Repository或Git Directory)
  • git仓库(Remote Directory)。

  • Git快速入门
  • 文件的四种状态
    • Untracked:未跟踪, 此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过 git add 状态变为Staged.
    • Staged:暂存状态. 执行git commit则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify状态. 执行git reset HEAD filename取消暂存,文件状态为Modified;
    • Mosified:文件已修改, 仅仅是修改, 并没有进行其他的操作.
    • Committed: 文件已提交修改;
  • Git文件状态流程图
  • .git 目录结构:进入隐藏的 .git 目录之后可以看到如上图所示结构
    • 核心文件: configobjectsHEADindexrefs 这 5 个文件夹

忽略文件

.gitignore文件用来忽略特定文件/文件类型

  • 但如果在.gitignore中添加文件将不能被提交。

因此,如果要克隆代码时忽略某些文件,但允许其他人向同一仓库提交这些文件,可以使用以下步骤:

  • 在.gitignore中添加要忽略的文件或文件类型。
  • 使用git clone 克隆代码,使用--filter选项来排除.gitignore中的文件。
    • 例如,克隆一个仓库并排除.gitignore中的*.log文件,可以使用以下命令:git clone --filter=tree:0 --no-checkout <repository_url>
  • 使用git checkout命令检出不包含.gitignore中的文件的工作树。
    • 例如,要检出刚刚克隆的仓库并排除.gitignore中的*.log文件,可以使用以下命令:git checkout HEAD -- .
  • 现在,已经克隆了代码并可让其他人提交.gitignore中忽略的文件。

主目录下建立 .gitignore 文件,如下规则:

  • 忽略文件中的空行或以井号(#)开始的行将会被忽略。
  • 用Linux通配符。
    • 例如:星号(*)代表任意多个字符,问号(?)代表一个字符,方括号([abc])代表可选字符范围,大括号({string1,string2,…})代表可选的字符串等。
  • 如果名称的最前面有一个感叹号(!),表示例外规则,将不被忽略
  • 如果名称的最前面是一个路径分隔符(/),表示要忽略的文件在此目录下,而子目录中的文件不忽略。
  • 如果名称的最后面是一个路径分隔符(/),表示要忽略此目录下该名称的子目录,而非文件(默认文件或目录都忽略)。

.gitignore 文件

新建

# 给 .gitignore 添加 .env 文件
echo ".env" >> .gitignore

git add .gitignore

人工设置

# 为注释
*.txt        # 忽略所有 .txt结尾的文件,这样的话上传就不会被选中!
!lib.txt     # 但lib.txt除外
/temp        # 仅忽略项目根目录下的TODO文件,不包括其它目录temp
build/       # 忽略build/目录下的所有文件
doc/*.txt    # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt

提交的准则

  1. 除了源码相关的东西之外,其他build产生的东西(如:maven的target文件夹,.idea文件夹等),均不能提交进入源码仓库,添加到 .gitignore 文件中忽略掉。
  2. 撰写规范的提交说明。一份好的提交说明可以帮助协作者更轻松更有效地配合工作。
  3. 要严格按照我们定的流程切换到指定分支,开发相应的功能。

创建 repo(项目)

gitlab 上创建新项目的几种方法

  • 全新项目
  • 已有目录
  • 已有git项目

git 账户设置

Git global setup

git config --global user.name "王奇文"
git config --global user.email "wangqiwen@163.com"

全新项目

Create a new repository

git clone git@code.x.com:wangqiwen.at/model_training.git
cd model_training
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master

已有文件目录

Existing folder

cd existing_folder
git init
git remote add origin git@code.x.com:wangqiwen.at/model_training.git
git add .
git commit -m "Initial commit"
git push -u origin master

已有项目(repo)

Existing Git repository

cd existing_repo
git remote rename origin old-origin
git remote add origin git@code.x.com:wangqiwen.at/model_training.git
git push -u origin --all
git push -u origin --tags

项目中如何选择分支模式

  • 【2021-3-26】Git原理及如何选择分支模式
  • 在项目开发的过程中,选择一个合适的分支模式来管理代码至为重要,那么如何根据这身的业务特点和团队规模来选择合适的分支模式呢?这部分将对几种主流的Git分支模式进行介绍,下边将介绍TBD主干开发模式)、Git-Flow模式、Github-FlowGitlab-Flow模式。
  • 分支总结: 根据每个项目的实际情况的不同选择不同的分支模式:
    1. git-flow模式对于开发周期长的项目是比较好的选择,可以很好解决新功能开发,版本发布,线上问题修复等问题;
    2. 如项目发布周期短,需持续发布维护,功能较为简单,TBD和GitHub-flow是个不错的选择;
    3. 如果对一些复杂功能的上线前增加一些验证,可选gitlab-flow模式。

还有一些其他的分支策略,比如定义一个主干分支,然后每个成员已自己名字命名的开发分支等等,结合我们的业务需求选择分支策略最为重要。

【2021-5-11】Google 和腾讯为什么都采用主干开发模式?, 《Google 工程效能三板斧之三:主干开发》 软件业界常用的软件分支模式有多种,但本质上可以分为两类:

  • 主干开发模式(Trunk Based Development)
    • 开发人员直接向主干(习惯上主干分支通常为:trunk 或 master)提交 / 推送代码。通常,开发团队的成员 1 天至少 1 次地将代码提交到主干分支。在到达发布条件时,从主干拉出发布分支(通常为 release),用于发布。若发现缺陷,直接在主干上修复,并根据需要 cherry pick 到对应版本的发布分支。
  • 特性分支开发模式(Feature Branch Development)
    • 为一个或多个特定的需求 / 缺陷 / 任务创建代码分支(branch),在其上完成相应的开发(一般经过增量测试)后,把它合并(merge)到主干 / 集成分支的开发模式。
    • 如:Git-Flow 模式、Github-Flow 模式和 Gitlab-Flow 模式等。这些模式只有细节上的差异

Google谷歌

互联网巨头 Google 大部分业务开发都采用主干开发模式,国内巨头腾讯也在推行主干开发(试点业务团队大部分已经采用)。

他们采用主干开发的原因在于对主干开发的优点有强烈诉求,而且有能力和资源弥补其缺点:

  • 都是互联网企业,竞争激烈,因此对迭代速度要求高;
  • 基础架构能力强:都能自研强大的持续集成平台,Google 有自研的 Forge,腾讯有自研的蓝盾;
  • 自动化测试能力强:都推行 TDD,强调开发负责质量,减少甚至取消手工测试人员(少量必要的手工测试转外包),自动化测试覆盖率高;
  • 都有严格的 CR 机制确保代码质量:Google 极其严苛的可读性认证(Readability)在业界已经是标杆,腾讯是国内少有正在采用类似实践的互联网企业。严格的代码可读性认证和根据此标准执行的严格代码评审制度,能有效的保证合入主干的代码质量不会降低。

主干开发的最大优点是:效率和质量,而这 2 者是软件和互联网企业的核心诉求。主干开发的缺点,巨头有能力和资源来填平这些坑。

因此,从 ROI(Ratio of Investment)的角度来看,Google 和腾讯采用主干开发实属必然。

Google 的工程效能(也叫研发效能)核心理念只有简单的 3 条:

  • 使用单体代码仓库(参考:Google 工程效能三板斧之一:单体代码仓库)
  • 使用 Bazel 构建(参考:Google 工程效能三板斧之二:使用 Bazel 构建)
  • 主干开发;

为了保证主干代码的质量,避免出现工程师合入到主干的代码 break 掉主干的情况,Google 采取了以下实践:

  • 代码合入事件触发通过持续集成,确保合入到主干的代码经过充分且必要测试;
  • 通过 Bazel 实现相关代码(指依赖变更代码的代码)的精准测试;
  • 至少 2 个合资格的 reviewer (代码评审人)的 LGTM(Look Good To Me),才允许代码合入主干;
  • 合资格的 reviewer 都是在 Google 内部通过 Readability (代码可读性)认证的员工;

腾讯在主干开发的实践

腾讯某 BG 在 2018 年开始的“930 变革”后,在各试点团队推动主干开发(注:并未全公司普遍采用),具体的举措包括:

  • 以度量牵引:通过对特性分支)的生命期监控和预警,实现非主干分支的生命期缩短,倒逼开发团队采用主干开发;
  • 投大力气统一 BG 内的持续集成工具、开发自动化测试平台;
  • 制定了 7 大编程语言的编码规范,并自研代码静态扫描工具;
  • 并参考 Google 推行代码可读性(Readability)、可测试性(Testability)认证制度;
  • 强力推行 CR (代码评审)制度,确保代码的可读性(命名、代码风格、设计、复杂度)。

效果:

  • 质量提升:代码质量从可测量的维度得到明显提升(代码规范率、单元测试覆盖率);
  • 迭代速度提升:试点团队的迭代周期从 4 周或 2 周提升至 1 周;
  • 代码从“私有”变“公有”:通过代码评审制度,提高了代码可读性,使代码从个人拥有(只有写代码的人能看懂),变成团队拥有(整个团队都能看懂);这一点对于企业非常重要,接手过别人代码的程序们都有感受;
  • 代码的自动化测试覆盖率提升明显,为未来的重构构筑了一张安全网;

中小企业

有些中小企业的技术决策者非常认可持续集成 / 持续交付的理念,从而更希望采用主干开发,但对于主干开发的缺点(或说弥补缺点的成本)存在顾虑。

对此,我有如下建议:

  • 基础架构要求:可以考虑采用开源软件,如持续集成采用 Jenkins、Travis CI、Gitlab CI 等,通过简单部署可以投入使用;同时配合代码静态分析工具(如 SonarQube、CheckStyle),确保代码基本质量过关;
  • 自动化测试要求:工具上不存在障碍,现代编程语言(如 java、go、c++)都有内建或第三方的单元测试框架;难点只在于成员的开发习惯,可以通过测试覆盖率工具,以增量覆盖率指标保证新增代码都有完备的自动化测试,从而逐步改变团队的研发文化;
  • 代码评审要求:开源的 Git 服务器(如 Gitlab)基本都支持 push hook,配合开源的 Gerrit 等 CR 工具,可以实现在代码推送(push)或 pull request(合入请求)时触发 1 个代码评审请求,实现评审通过后,代码才正式合入的功能;剩下的就是研发文化问题了,需要在团队内部推行代码规范、代码可读性等宣导和教育工作;
  • 发布时的特性开关:如果要求不高,可以通过代码 hard code 一个常量作为特性开关;如果要求高,也有开源的特性开关(比如:unleash、piranha、flipper)工具可供选择。参考上述建议,并充分认识到主干开发的成本和困难的情况下,中小企业开发团队也并非不可以考虑主干开发的实践

TBD(主干开发模式)

  • TBD,即主干开发模式,所有的开发都在一个开发分支上进行协作开发,只保留一条长期稳定的开发分支,不允许新建任何长期存在的开发分支,任何代码的变更都更新到主干分支上,当需要发布时,建议根据版本号拉一个release分支进行发布,可以通过merge或者cherry pick将代码弄到发布分支上。

TBD模式注意点:

  1. 因为所有的改动及变更都在主干分支上,所以确保改动足够小,每次的改动都是可控的,能段时间完成验证;
  2. 每次主干分支上的改动能得到快速验证,有完善的团队协作及自动化测试,随时做好上线的准备,避免引主干上的功能缺陷而影响发布。

因为主干开发要求每次变更提交都要小,并且要快速验证完,保证主干是处在可发布状态。对于一些处在开发过程中的特性,如每次变更提交,并非意味着完整特性的完成,为了隔离“特性半成品”对主干的影响,一般会采用特性开关(Feature Toggle)的方式进行隔离。即频繁的代码变更提交,可以先做集成及验证,但是在发布的角度,通过(Feature Toggle)先隐藏相关特性,只有当特性都完成之后,才打开开关,特性完全透出。

TBD模式优点:

  1. 分支少,合并冲突小,实践简单;
  2. 适合持续交付及部署,简单密集需求交付

TBD模式缺点:

  1. 对团队协作及成熟度合集成测试有很高的要求;
  2. 不适合开发一些持续时间长的需求及功能复杂的业务;

Git-Flow模式

  • 随着敏捷开发的广泛使用,越来越多的团队协作完成某一特性或者分别完成不用的用户故事,根据不同的特性或者用户故事来创建开发分支就应运而生。最有代表性的就是Git-Flow模式。
  • Git-Flow 模式很好解决了不同特性之间并行开发需要的工作方式。每一个特性都能同时开工,结合敏捷开发的例子,每个迭代开始时从主干分支拉出一个特性分支,命名结构参考feature/xxx-232,所有关于此特性的开发都在此分支上进行,当开发完成后把特性分支合并回主干分支上,测试通过后进行发布。

Git原理及如何选择分支模式

Git-Flow模式一般有以下分支结构:

  • feature 分支:开发者进行特性功能开发的分支;
  • develop 分支:开发主干分支,包含所有的特性功能;
  • release 分支:版本发布分支;
  • master 分支:稳定分支,保存最新的已发布代码;
  • hotfix 分支:线上问题缺陷修复分支;

工作流程:

  • 在开发者接到一个开发需求时,从develop分支拉一个feature分支进行开发,最好已ID进行命名,避免重复,为了减少后边合入develop的冲突,最好在开始coding前把develop分支合到feature分支上再进行开发;
  • 当在feature分支完成开发并验证通过后,将feature分支合入develop分支;
  • develop分支用于集成功能验证,当集成测试成功后将基于develop分支拉一个release版本分支进行发布,如果在release上测试发现bug则在release上修复,之后将代码合入develop,当上线完成后将release合入master分支进行最新上线代码保存;
  • 如果线上发现bug,则基于master拉一条hotfix分支进行修复,修复完成后将hotfix分支合入master进行发布,最后将hotfix代码也同步到develop上。

注意:对一些已完成的feature分支及hotfix分支进行及时删除。

【2021-4-20】Git Flow工作流

Git-Flow模式的优点

  1. 特性并行开发,效率高,代码独立;
  2. 支持复杂业务、大团队协同开发;
  3. 支持多版本发布;

Git-Flow模式的缺点

  1. 分支多,合并冲突较为频繁
  2. 需要进行维护分支,对分支代码进行更新

【2021-12-15】Git Flow 工作流程使用寿命

分支简述

主要分支简述

  • 天蓝色圆点 所在的线源码的主线(master)。
    • master分支用来记录官方发布轨迹
    • 天蓝色方形 指向的节点就是每一个发布版本的标签(tag)。
  • 紫色圆点 所在的线为主要分支线(develop)。
    • 集成分支,用来记录开发新功能的轨迹。
  • 注意:
    • 除了 master 主线和 develop 主分支线,其他的分支都是临时分支,有一定的生命周期的,其余的工作流程分支都是围绕这两个分支之间的区别进行的。
  • 其它分支
    • 橙色圆点 所在的线为新功能开发分支线(feature)。
      • 每一个新的功能都应该创建一个独立的分支,从develop分支中派生出来。当功能完成后,要合并(merged)回develop分支,合并后它的生命周期就结束。新功能分支不会与master分支有直接的交汇。
      • 所有新功能分支会合并到develop分支。但这个Gitflow工作流不会在此结束。
    • 绿色圆点 所在的线为新版本发布线(release)。
      • 一旦开发的功能已经满足发布条件(或预定发布日期接近),应该合并所有满足发布条件的新功能分支到develop分支中
      • 然后开一个发布分支(Release)发布版本。这个分支不能再添加新的功能,只有bug修复和该版本为导向的任务。
      • 一旦到了发布日期,Release就要合并回master发布,并打出版本标签。
      • 另外,还需要合并回develop分支。
    • 红色圆点 所在的线为发布版本bug修复线(hotfix)。
      • 维护分支也就是线上bug修复分支,使用来快速修复生产环境的紧急问题。
      • 唯一一个开放过程中直接从master分支派生来的分支。快速的修复问题后,它应该被合并回master和develop(或者当前发布分支),然后,master分支需要打一个版本标签。
      • 一个专门的错误修复开发线,可以让团队在不等待下一个发布周期,导致中断工作流程情况下解决问题。可以将维护分支当做主要的问题修复分支,与master并行。

命名约定

  • 主分支名称: master
  • 主开发分支名称: develop
  • 标签(tag)名称:v.RELEASE,其中”“ 为版本号,“RELEASE”大写,如:v1.0.0.RELEASE
  • 新功能开发分支名称:feature-* or feature/,其中 “” 为新功能简述,如:feature-item-activity-list
  • 发布分支名称:release-* or release/*,其中 * 为版本号,“release”小写,如:release-1.0.0
  • master的bug修复分支名称:hotfix-* or hotfix/*,其中 * 为bug简述,如:hotfix/item-update-bug

Github-Flow 模式

  • Github-Flow就是简化版的Git-Flow,更轻量,减少分支。对于 GitHub-Flow 来说,发布应该是持续地,当一个版本准备好,它就可以被部署,feature跟hotfix本质上都是一样的,都属于特性分支,并移除了release分支。

分支情况如下:

  • 在master分支上的代码都是最新的,可部署的;
  • 在特性分支合到master分支时需要发起Pull Request代码评审,评审后方可合入master;
  • 在master上进行持续版本发布。

优点:

  1. 支持并行开发;
  2. 分支结构简单,有明确的规则定义,持续集成持续部署

缺点:

  1. 对测试要求高,一些功能复杂的需求需要持续长的时间验证或者中断则影响整个计划;
  2. 不能很好的处理一些很紧急的上线需求;

Gitlab-Flow 模式

GitLab-Flow 相比于 GitHub-Flow 来说,在开发侧的区别不大,只是将 pull request 改成了 merge request,而 merge request 的用法与 pull request 类似,都可以做为代码评审、获取反馈意见的一种沟通方式。

最大的区别体现在发布侧,即引入了对应生产环境的 production 分支和对应预发环境的 pre-production 分支(如果有预发环境的话)。这样,master 分支反映的是部署在集成环境上的代码,pre-production 分支反映的是部署在预发环境的代码,production 分支反映的最新部署在生产环境的代码。

当一个特性开发完成,提交 merge request,将特性开发的代码合并到 master,并部署到集成环境进行验证;当验证通过之后,提交 merge reqeust,合并 master 到 pre-production 分支,并部署到预发环境,进行预发环境上验证;当预发环境验证成功之后,再提交 merge request,将 pre-production 分支上的代码合并到 production 分支上。

常用命令

#添加所有你修改的文件到暂存区
git add -A
#把本地的备注提交到暂存区
git commit -m"[message]对你修改过代码一个备注"

# 拉取远程仓库,并与本地仓库的代码合并
# git pull [remote]  [branch]
# 查看变更信息或者冲突
git status
# 修改 .gitignore 文件,可以省略不必要的文件跟踪

# 查看提交的历史
git log 
  • Git对比两个分支
  • Git Clone克隆仓库速度太慢怎么办?
    • 修改Hosts:分别解析http://ithub.global.ssl.fastly.net和http://github.com网站的ip地址,加入host中;mac刷新host文件,sudo killall -HUP mDNSResponder
    • 使用码云:
      • (1) 使用git clone git@gitee.com:Evllis/novice.git克隆仓库到本地
    • cgit(git换cgit)
      • 安装:git clone https://github.com/killf/cgit.git && sudo ./cgit/install.sh
      • 使用:cgit clone https://github.com/killf/cgit.git (亲测有效)

【2021-4-1】git思维导图

config

# 【2020-8-21】
git config --list 
git config -l # 查看已有配置列表
git config -e # 直接编辑配置信息
git config --global user.email "输入你的邮箱" # 设置变量
git config --global user.name "输入你的用户名"
git config --global --replace-all user.email "输入你的邮箱" # 覆盖已有变量
git config --global --replace-all user.name "输入你的用户名"
git config   --global --unset  user.name # 取消命名

# 生成公钥
ssh-keygen -t rsa
# 公钥位置,添加到GitHub里的setting设置中
cat ~/.ssh/id_rsa.pub

clone

git中clone项目有两种方式:HTTPSSSH,区别如下:

  • HTTPS:不管是谁,拿到url随便clone,但是在push的时候需要验证用户名密码
  • SSH:clone的项目必须是拥有者、管理员,而且在clone前添加SSH Key。SSH 在push的时候,是不需要输入用户名的,如果配置SSH key的时候设置了密码,则需要输入密码的,否则直接是不需要输入密码的。
# 下载一个项目,默认master分支
git clone [url]
git clone --recursive [url] # 【2021-5-7】用于循环克隆git子项目(包含别的仓库代码), 一次性解决模块依赖
# git clone 中途报错(early EOF),进入主目录,补充执行以下命令
git submodule update --init --recursive 
# 获取某个分支 dev-md 代码
git clone -b dev-md https://gitee.com/mindspore/mindscience.git

ssh

在git中使用SSH Key的步骤:

  • 检查电脑是否存在SSH Key:$ cd ~/.ssh$ ls
  • 如果存在id_rsa.pub 或 id_dsa.pub 文件,说明文件以及存在,跳过创建SSH Key步骤。
  • 创建SSH Key
  • 将公共的SSH 放到远程仓库上

sumodule

Git 用子模块 submodule 管理嵌套项目,submodule 允许将一个 Git 仓库当作另外一个Git 仓库的子目录。这允许你克隆另外一个仓库到你的项目中并且保持提交相对独立。

# 将第三方模块 vimwiki-assets 放到 assets 子目录中
git submodule add https://github.com/maonx/vimwiki-assets.git assets
# 状态检查:目录有增加1个文件.gitmodules
git status
git submodule # 查看子模块
git submodule update # 更新子模块到最新版本
git submodule update --remote # 更新子模块为远程最新版本

克隆包含子模块的项目,有两种方法:

  • 一种是先克隆父项目,再更新子模块;
    • 初始化模块只需在克隆父项目后运行一次。
  • 另一种是直接递归克隆整个项目。

克隆父项目,再更新子模块

# (1) 克隆父项目
git clone https://github.com/maonx/vimwiki-assets.git assets

git submodule # 查看子模块, 子模块前面有一个-,说明子模块文件还未检入(空文件夹)。
# -e33f854d3f51f5ebd771a68da05ad0371a3c0570 assets
#  初始化模块只需在克隆父项目后运行一次。
git submodule init # 初始化子模块
git submodule update # 更新子模块

# (2) 递归克隆整个项目
git clone https://github.com/maonx/vimwiki-assets.git assets --recursive 
# 递归克隆整个项目,子模块已经同时更新了,一步到位。

# 修改子模块
# 在子模块中修改文件后,直接提交到远程项目分支。
git add .
git ci -m "commit"
git push origin HEAD:master
# 删除子模块
# 删除子模块比较麻烦,需要手动删除相关的文件,否则在添加子模块时有可能出现错误
# 同样以删除assets文件夹为例

git rm --cached assets # 删除子模块文件夹
rm -rf assets # 删除.gitmodules文件中相关子模块信息
# [submodule "assets"]
#  path = assets
#  url = https://github.com/maonx/vimwiki-assets.git
# 删除.git/config中的相关子模块信息
# [submodule "assets"]
# url = https://github.com/maonx/vimwiki-assets.git
rm -rf .git/modules/assets # 删除.git文件夹中的相关子模块文件

【2021-5-21】第三方库

# 直接把第三方的版本库合并到自己的库中. 示例如下:
git clone https://git.oschina.net/gaofeifps/body.git # 主库
cd body
git submodule add https://git.oschina.net/gaofeifps/leg.git # 添加第三方库
git status # 多了一个 leg的库, 和一个.gitmodules的文件, 现在提交一下
git commit -am "add leg"
git push
# 版本库中不会存第三方引入库的实体文件, 而是通过 .gitmodules的方式存储三方的联系方式, 当下载到本地运行的时候才会再拉取文件
# 而且这个时候在其他的地方安装body这个库的时候直接运行 git clone 是生成不了完整的文件的, 缺少了 leg库的文件
# 因为这个时候的 body/leg目录是空的需要多走一步, 这时为什么呢? 
git clone https://git.oschina.net/gaofeifps/body.git
git submodule init && git submodule update
#下面这一句的效果和上面三条命令的效果是一样的,多加了个参数  `--recursive`
git clone https://git.oschina.net/gaofeifps/body.git --recursive # 获取完整库
git submodule foreach git checkout master # 批量更新所有第三方库,按照 .gitmodules会根据path寻找所有的三方模块, 并在每一个模块中都执行 foreach 后的命令
git submodule deinit <submodule-name> # 删除第三方库
# 作者:guanguans,https://www.jianshu.com/p/e27a978ddb88

log

# [2020-9-1]
git log # 查看历史提交信息
git log –follow [file] # 列出了文件的版本历史记录,包括文件的重命名。
# git对比分支代码
git log dev ^master # dev 有, master没有
git log master ^dev # master有,而dev没有
git log master..dev # dev比 master 中多提交了哪些内容
git log dev..master # master 比 dev 多提交了什么
git log dev...master # 仅仅查看有什么不一样
git log --left-right dev...master # 每次提交都在哪个分支上
# 注意 commit 后面的箭头,根据我们在 –left-right dev…master 的顺序,左箭头 < 表示是 dev 的,右箭头 > 表示是 master的。
git log --pretty=oneline # 精简模式:单行
# 设置别名
alias gitp='git log --pretty=oneline' # 单行模式
alias gitg="git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit" # 图模式
git config --global alias.s status # git别名 git s
git show [commit] # 显示指定提交的元数据和内容更改。

# 【2020-9-10】git免密pull/push,以下命令自动保存密码
git config --global credential.helper store

fetch

git fetch 有四种基本用法

  1. git fetch
    • 这将更新git remote 中所有的远程repo 所包含分支的最新commit-id, 将其记录到.git/FETCH_HEAD文件中
  2. git fetch remote_repo
    • 这将更新名称为remote_repo 的远程repo上的所有branch的最新commit-id,将其记录。
  3. git fetch remote_repo remote_branch_name
    • 这将这将更新名称为remote_repo 的远程repo上的分支: remote_branch_name
  4. git fetch remote_repo remote_branch_name:local_branch_name
    • 这将这将更新名称为remote_repo 的远程repo上的分支: remote_branch_name ,并在本地创建local_branch_name 本地分支保存远端分支的所有数据。

FETCH_HEAD: 是一个版本链接,记录在本地的一个文件中,指向着目前已经从远程仓库取下来的分支的末端版本。

stash

文件修改

# 文件修改
# ① 多步命令
mv a b
git rm a
git add b
# ② git mv 一步到位
git mv a b # git mv命令用于重命名或移动文件, 等效于 git rm + git add

git rm file # 从你的工作目录中删除文件,然后进行删除。
git rm --cache file # 已暂存的状态转换为未暂存

git stash save # 临时存储所有已修改的跟踪文件
git stash pop # 恢复最近存放的文件。
git stash list # 列出所有隐藏的变更集。
git stash drop # 将丢弃最近存放的变更集。
git stash apply # 恢复工作现场
git stash apply stash@{0} # 恢复指定的工作现场,当你保存了不只一份工作现场时

git merge dev # 合并分支dev到master

git tag [commitID] # 用于将标签赋予指定的提交。
#或者恢复暂存区的指定的某个文件到本地工作区
git checkout [file]

reset

# 在commit之后撤销修改的情况下:
# 重置到上一次暂存区版本
git reset --hard [版本号]
# 或者不管的情况下直接重新修改代码再commit一次
# 或者通过使用git log查看版本号后回退到暂存区的某个版本
git reset [版本号]
# 【2020-9-8】 
git reset [file] # 取消暂存文件,但保留文件内容
git reset [commit] # 在指定的提交后撤消所有提交,并在本地保留更改。
git reset --soft 19462f6f46cf4cbc211d366359afac0c17a7c190
git reset –hard [commit] # 将丢弃所有历史记录,并返回到指定的提交
# 注意 --hard 参数会抛弃当前工作区的修改
# 使用 --soft 参数的话会回退到之前的版本,但是保留当前工作区的修改,可以重新提交
git push  --forced # 远程推送的话
git remote add [variable name] [Remote Server Link] # 将本地存储库连接到远程服务器。
# 更新master → release分支的操作步骤
git branch release # 创建release分支,用于上线
git checkout release # 切换到release分支
git merge master -m '合并到release分支' # 合并master到本地
git push origin release # 同步到远程分支
# 撤销merge操作
git revert 【方法二撤销merge时提交的commit的版本号,这里是88edd6d】
git revert -m 【要撤销的那条merge线的编号,从1开始计算(怎么看哪条线是几啊?)】 【merge前的版本号】

diff

git diff # 此命令显示尚未暂存的文件差异,查看当前没有add 的内容修改
git diff HEAD # 查看当前没有add和commit的改动
git status # 同上
git diff --cached # 查看已经add 没有commit 的改动
git diff –staged # 此命令显示暂存区域中的文件与当前最新版本之间的差异
git diff 版本号码1 版本号码2 # 查看任意两个版本之间的改动
git diff 版本号码1 版本号码2  src # 比较两个版本号码的src 文件夹的差异
git diff [first branch] [second branch] # 两个分支之间的差异

# 查看某个文件谁改过代码
git blame filename

add

git add -A # 提交所有变化( -A  ==  --all )
git add -u # 提交被修改(modified)和被删除(deleted)的文件,不包括新文件(new)。( -u  ==  --update)
git add . # 提交新文件(new)和被修改(modified)文件,不包括被删除(deleted)文件
git add <path> # 等同于 git add .
git add -h # git add 查看帮助,git add --help可以查看更详细内容

pull

git pull 操作其实是git fetch 与 git merge 两个命令的集合。

  • git pull 等效于先执行 git fetch origin 当前分支名, 再执行 git merge FETCH_HEAD.

如果要合并代码就并不一定要用git merge命令了,也可以用git pull命名的,比如要把远程origin仓库的 xx 分支合并到本地的 yy 分支,可以有如下两种做法。

#(1)第一种,传统标准的做法:
# 举例说明:将远程origin仓库的xx分支合并到本地的yy分支。
git fetch origin xx # fetch到远程仓库目标分支的最新commit记录到  ./git/FETCH_HEAD文件中
git checkout yy # 切换到要合并的分支
git merge FETCH_HEAD # 将目标分支最新的commit记录合并到当前分支

# (2)第二种,直接使用pull命令,将远程仓库的目标分支合并到本地的分支:
# git pull <remoterepo_name> <branch_name> 
# 举例说明:将远程origin仓库的xx分支合并到本地的yy分支
git checkout yy
git pull origin xx
# (3)第三种
git checkout xx
git pull   # 如果本地没有xx分支的,这一步都可以不执行。
git checkout yy  # 切换到yy分支
git merge xx # 将xx分支合并到yy分支  这一步可以加上 --no-ff 参数,即 git merge --no-ff

push

git  pull orgin master # 将本地master拉取到远程仓库origin的master分支
# 上传本地指定分支到远程仓库
git push [remote] [branch]
git push origin master # pull大致同理
git push –all [variable name] # 将所有分支推送到你的远程存储库。
git push [variable name] : [branch name] # 删除远程存储库上的分支

branch

git 分支分为远程分支和本地分支

  • * 开头表示本地分支
  • remote 是远程分支

本地分支与远程分支映射关系名称可以不同

  • 建立映射关系(或跟踪关系 track)。
  • 这样使用 git pull 或者 git push 时就不必每次指定从远程分支拉取合并,推送到哪个远程分支了。
# 查看映射关系
git branch -vv
# * dev    31c44ca [origin/dev: ahead 5] 删除文件
#  master 847e219 [origin/sentencebert_session] [fix]local_rank问题

# 建立当前分支与远程分支的映射关系:
git branch -u origin/addFile
# 或者使用命令:
git branch --set-upstream-to origin/addFile

# 撤销本地分支与远程分支的映射关系
git branch --unset-upstream

branch + checkout

#没有commit到暂存仓库的情况下:
# 恢复之前上一次暂存区的所有文件到工作区
git branch # 查看本地分支
git branch dev #创建分支dev
git checkout dev #切换到分支dev
git branch -r # 查看所有远程分支
git branch -a # 查看存储库的所有当前分支,包括本地和远程分支。
git branch -a --merged # 合并到当前分支的所有分支
git checkout -b dev # 创建并切换到分支dev
git checkout -b dev origin/dev # 创建远程dev分支轨迹版本
git branch -d dev # 删除分支
git branch -D branch_2 # 删除本地分支,即使尚未合并,这也会删除该分支!
git push origin :dev # 删除远程分支

git push origin dev # 注意:本地分支提交后,别人才能看到分支
git push -u origin develop # 推送到服务器

git checkout -- myfile #从本地仓库恢复文件(用于撤销本地修改)
git checkout 
git checkout 分支名称 # 切换分支

【2024-4-19】更改分支名称

  • sentencebert_session -> master
git checkout sentencebert_session # 切换到目标分支
git branch # 核实
git branch -m master # 重命名(注意是本地分支)
git push origin # 同步到命名到远程
# git branch -m old-branch new-branch

修改远程分支

# 先将本地分支重命名
git branch -m oldBranch newBranch
# 删除远程分支(远端无此分支则跳过该步骤), 默认分支无法删除
git push --delete origin oldBranch
# 将重命名后的分支推到远端
git push origin newBranch
# 把修改后的本地分支与远程分支关联
git branch --set-upstream-to origin/newBranch

cherry-pick

git 教程 –git cherry-pick 命令

一般代码的合并分为两种:一种是整个分支的合并,一个是挑选部分的commit来合并, 使用指令git cherry-pick。

git cherry-pick基础用法

# ------ (1)基础用法 --------
# 挑选一个commit-id合并
# 注意:合并过来的commit-id将会变掉,产生一个新的commit-id,跟原来的不在相同
git cherry-pick commit-id

# 挑选多个commit-id合并
git cherry-pick commit-idA commit-idB

# 挑选连续的多个commit-id合并
# 该指令是将从commit-idA开始到commit-idB之间的所有commit-id提交记录都合并过来,需要注意的是,commit-idA必须比commit-idB提前提交,也就是说在被挑选的分支上,先有的commit-idA,然后才有的commit-idB
git cherry-pick commit-idA..commit-idB

# 第一步:需要合并人解决对应的冲突文件,然后提交到暂存区
git add . 
# 第二步:使用下面的命令继续执行
git cherry-pick --continue

(2)高级用法

使用上面的指令基本上可以玩转很大部分的场景,但是总有一些我们预想不到或者相对不是很丝滑的场景

① 合并冲突:

  • 在实际合并的过程中,总有一些冲突的情况,遇到这些情况下,该如何使用cherry-pick的组合命令来解决问题?
  • 首先在使用cherry-pick时,如果遇到了代码冲突,其实合并过程会停止,需要使用其他的方式来继续对应的操作

② 继续合并–continue

  • 第一步:需要合并人解决对应的冲突文件,然后提交到暂存区
    • git add .
  • 第二步:使用下面的命令继续执行
    • git cherry-pick –continue

③ 放弃合并,回归原始状态–abort

  • 使用当前的指令,合并的动作暂停,并且回归到操作前的样子
    • git cherry-pick –abort

④ 放弃合并,保留状态 –quit

  • 使用当前的指令,会保留车祸现场,退出cherry-pick
    • git cherry-pick –quit

git commit

规范 commit不仅有助于他人review, 有效输出改动日志,通过一些工具就可以自动生成版本变动内容

Git Commit 应该包含以下部分:

  • 类型:表示此次提交的类型,如 feature(新功能)、bugfix(修复 bug)、docs(文档更新)等。
  • 范围:此次提交影响的范围,如模块、组件、服务等。
  • 描述:简要描述此次提交的内容。

commit message 格式如下:

<type>[optional scope]: <description>
# 空一行  
[optional body]
# 空一行  
[optional footer]
  • type 用于表示此次改动的类型,常用几种:
    • feat 新功能(feature)表示在代码库中新增了一个功能(这和语义化版本中的 MINOR 相对应)
    • fix 表示在代码库中修复了一个 bug(这和语义化版本中的 PATCH 相对应)
    • docs 文档更新(documentation)
    • style (格式化, 缺失分号等; 不包括生产代码变动)
    • refactor (重构代码)
    • perf (性能优化)
    • test (添加缺失的测试, 重构测试, 不包括生产代码变动)
    • chore (更新grunt任务等; 不包括生产代码变动)
  • scope:可选修改范围,标识此次提交主要涉及到代码中哪个模块。
  • description:简明扼要描述本次提交的目的(一般不超过30个字符比较好),首字母无需大写,结尾不需要使用.。
  • optional body:详细描述本次提交,比如此次变更的动机,如需换行,则使用 |
  • optional footer:描述与之关联的 issue 或 break change。

vscode工具可安装插件 git-commit-plugin,一款自动生成规范git提交信息的插件。

git lfs 大文件

【2021-6-7】git大文件管理,Git LFS操作指南

  • Git LFS(Large File Storage, 大文件存储)是可以把音乐、图片、视频等指定的任意文件存在 Git 仓库之外,而在 Git 仓库中用一个占用空间 1KB 不到的文本指针来代替的小工具。通过把大文件存储在 Git 仓库之外,可以减小 Git 仓库本身的体积,使克隆 Git 仓库的速度加快,也使得 Git 不会因为仓库中充满大文件而损失性能。
  • 使用 Git LFS,在默认情况下,只有当前签出的 commit 下的 LFS 对象的当前版本会被下载。此外,我们也可以做配置,只取由 Git LFS 管理的某些特定文件的实际内容,而对于其他由 Git LFS 管理的文件则只保留文件指针,从而节省带宽,加快克隆仓库的速度;也可以配置一次获取大文件的最近版本,从而能方便地检查大文件的近期变动。详见后文进阶使用

普通场景不论是针对小型的代码文本文件、还是比较大型的图片文件,在相关变更从本地提交到远端仓库时,所有的相关文件资源都会完整的存储在git server。就图片中的例子而言,如果图片文件越来越多,改动频次越来越大,仓库的体积将极速膨胀起来。

Git 是业界流行的分布式版本控制工具,本地仓库与远端仓库同样保存了全量的文件和变更历史,这样让代码协作变得简单和高效。但也正因为如此,Git针对大型文件(例如图片、视频或其他二进制文件)的版本控制,也会存在一些问题,主要有两点:

  • 效率变慢:不管实际上用户是否使用到这些大文件的历史,都需要把每一个文件的每一个版本下载到本地仓库。毫无疑问,下载耗时的增加给用户带来了更多的等待时间。
  • 空间变大:一个Git仓库存放的大型的文件越多,加之伴随着其关联提交不断增多,Git仓库会以非常快的速率膨胀,占用更多的磁盘空间。

Git LFS 为了解决大文件托管的效率问题,提供了五大特性,抽象看来为:

  • 更大:支持GB级别的大文件版本控制。
  • 更小:让Git仓库空间占用减小。
  • 更快:仓库的克隆和拉取更快。
  • 透明:Git使用上对用户完全透明。
  • 兼容:权限控制上完全兼容(兼容Codeup权限控制)。

LFS处理流程

参考:如何使用Git LFS

安装

curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
yum install git-lfs
git lfs install

使用方法

  • 执行 git lfs install 开启lfs功能
  • 使用 git lfs track 命令进行大文件追踪 例如git lfs track “*.png” 追踪所有后缀为png的文件
  • 使用 git lfs track 查看现有的文件追踪模式
  • 提交代码需要将gitattributes文件提交至仓库. 它保存了文件的追踪记录
  • 提交后运行git lfs ls-files 可以显示当前跟踪的文件列表
  • 将代码 push 到远程仓库后,LFS 跟踪的文件会以『Git LFS』的形式显示:
  • clone 时 使用’git clone’ 或 git lfs clone均可

限制

  • Window平台,单个文件不支持超过4G,issues 2434
  • Window用户必须保证已经安装Git Credential Manager,否则可能导致操作被无限挂起,issues 1763
  • 不同于Gitlab硬编码的LFS下载token超时时间(30分钟),Codeup会根据将要下载的文件列表动态计算token超时时间,但是如果位于网络环境不好的环境,仍旧可能导致token超时的情况。如果需要根据需求调整,可以联系Codeup系统管理员处理。

git 命令问题

dev分支 push被拒

【2021-9-28】参考地址,错误信息:

To https://git.lianjia.com/aisearch/speech/nlu-service.git
 ! [remote rejected] dev-wqw -> dev-wqw (pre-receive hook declined)
error: failed to push some refs to 'https://git.lianjia.com/aisearch/speech/nlu-service.git'

分析:

  • 原因1:本地git没有配置好用户信息
    • 解决:添加配置信息
      • 配置gitlab的邮箱:git config user.email jojo.jiang@XXXXadmin.com
      • 配置gitlab用户名:git config --global user.name “jojo.jiang”
      • 查看:git config --list
      • 随便修改某个文件,直接提交:git push origin dev-wqw (这个步骤不能省)
  • 原因2:自身权限不够(mainteiner以下),dev分支被protected
    • 解决:找管理员提升权限

【2024-3-15】命中原因2,解决方案

  • 进入 Gitlab 页面
  • 侧边栏 Settings -(弹出次级菜单)-> Repository -(进入设置页)-> 展开右侧 Protected Branches -(找对应分支,master/branch)-> 设置权限(Allowed to merge/push), 赋权 (Developers + Maintainers)

OpenSSL SSL_read

  • 现象:windows下git pull,出错:

fatal: unable to access ‘https://github.com/wqw547243068/wqw547243068.github.io.git/’: OpenSSL SSL_read: Connection was reset, errno 10054

  • 解决方法
    • 参考解法,有多种原因,如文件名或路径太长
    • git config –global core.longpaths true

443

  • 执行git push,错误提示:

fatal: unable to access ‘https://github.com/wqw547243068/wqw547243068.github.io.git/’: Failed to connect to github.com port 443: Timed out

  • 解法
    • Internet与网络的设置,有代理导致,需要勾选:自动检测设置,详见

速度慢

不能撤销本地修改(error:path…is unmerged)

【2021-12-1】不能撤销本地修改(error:path…is unmerged)

  • 做了错误操作,应该先进行重置,先取消暂存文件,然后签出,再恢复本地更改。
git reset foo/bar.txt # 重置
git checkout foo/bar.txt # 恢复本地

fatal: Not possible to fast-forward, aborting.

【2023-3-21】 vscode上执行同步(git pull & git push)时,报错误信息

fatal: Not possible to fast-forward, aborting.

stackoverflow: Why is Git not allowing me to fast forward merge anymore? If I try to force it using –ff-only, I get the message

fatal: Not possible to fast-forward, aborting.

I realize that there are huge advantages to merge –no-ff, but I’m just puzzled why I can’t –ff-only now?

解法

Use the option –no-ff to turn off fast-forwarding for one pull:

git pull --no-ff

github 访问问题

  • 【2021-3-18】github访问受限,速度慢, 知乎专题:github打开慢?无法访问?
    • (1)修改 HOSTS 文件进行加速,手动把cdn和ip地址绑定
      • 第一步:获取 github 的 global.ssl.fastly 地址访问:http://github.global.ssl.fastly.net.ipaddress.com/#ipinfo 获取cdn和ip域名,得到:199.232.69.194 https://github.global.ssl.fastly.net
      • 第二步:获取github.com地址, 访问:https://github.com.ipaddress.com/#ipinfo 获取cdn和ip,得到:140.82.114.4 http://github.com
      • 第三步:修改 host 文件映射上面查找到的 IP
        • windows系统:1、修改C:\Windows\System32\drivers\etc\hosts文件的权限,指定可写入:右击->hosts->属性->安全->编辑->点击Users->在Users的权限“写入”后面打勾。然后点击确定。
        • 2、右击->hosts->打开方式->选定记事本(或者你喜欢的编辑器)->在末尾处添加以下内容:199.232.69.194 github.global.ssl.fastly.net 和 140.82.114.4 github.com
      • 附:DNS查询工具IPaddressswitchhost管理hosts文件
    • (2)Gitee中转fork仓库,如码云,导入github项目即可,web编辑,还能同步到github示例项目
    • (3)GitHub镜像源,克隆版的 GitHub,你可以访问上面的镜像网站,网站的内容跟 GitHub 是完整同步的镜像, 如网站: fastgit,cnpmjs,
    • (4)仅查看代码:github.com → github1s.com,就能按照vs code模式查看代码
  • Github 加速下载
    • 只需要复制当前 GitHub 地址粘贴到输入框中就可以代理加速下载!地址
    • GitHub raw 加速:GitHub raw 域名并非 github.com 而是 raw.githubusercontent.com,上方的 GitHub 加速如果不能加速这个域名,那么可以使用 Static CDN 提供的反代服务。将 raw.githubusercontent.com 替换为 raw.staticdn.net 即可加速。
    • 进入指定网站(zhlh6toolwa),输入 Github 仓库地址,使用生成的地址进行 git ssh 等操作
    • 谷歌浏览器GitHub加速插件:
      • 链接: https://pan.baidu.com/s/1u_lBrU4S8jG5KCu2gscsTQ
      • 提取码: i21n
    • gitclone缓存加速网站
  • 参考:github镜像加速
  • github与gitee同步
    • 终端下同时连接github和gitee,设置方法:vim ~/.git/config
[remote "origin"]
	url = https://gitee.com/wqw547243068/wqw547243068.github.io.git
   url = https://github.com/wqw547243068/wqw547243068.github.io.git
	fetch = +refs/heads/*:refs/remotes/origin/*

交互式学习

结束


支付宝打赏 微信打赏

~ 海内存知已,天涯若比邻 ~

Share

Related Posts

标题:Jupyter notebook 学习笔记

摘要:Jupyter notebook 使用技能总结

标题:傅里叶变换-Fourier Transform

摘要:经典数学知识点:傅里叶变换

Comments

--disqus--

    Content
    My Moment ( 微信公众号 )
    欢迎关注鹤啸九天