#19 WSL git 太慢

2023-10-15

使用 WSL 的时候 git 用得简直令人难受,每次切换环境(Windows 和 WSL),都需要 Refresh Index,一次就得二十几秒。

最后只好搞一个别名:

# 5.15.90.1-microsoft-standard-WSL2
if [[ "`uname -r`" == *WSL2 ]]; then
    SHMODE=wsl
fi

if [[ $SHMODE == "wsl" ]]; then
    alias git=git.exe
fi

这是我的本地环境中截出来得一点,其实还做了一些其他得适配,总算能够接受了。

原因

暂时没有读到相关资料。
WSL 已经出来很久了,可是这些性能问题微软还是没有解决,可能是他们不想解决。

参考资料与拓展阅读

#18 Git LFS

2023-04-26

开源中国文章 紧跟 AI 步伐, Gitee 已支持 AI 模型托管 中介绍了 Git LFS 的使用。

结合 git lfs help,记录如下:

  1. 需要先 install 一下,启用 LFS 功能
$ git lfs install
Updated Git hooks.
Git LFS initialized.
  1. 追踪大文件
git lfs trace path/to/largefile
# 会记录在 .gitattributes 文件中
# path/to/largefile filter=lfs diff=lfs merge=lfs -text
  1. 推送大文件
# 正常提交
git add .gitattributes path/to/largefile
git commit -m "..."

# 推送
git lfs push --all
git lfs push --all origin
  1. 拉取大文件
git lfs pull --all

# 指定文件
git lfs pull -I <filepath>
  1. git lfs ls-files 列出大文件

#17 Git 仓库迁移学习

2023-03-13

看到一篇公众号文章 《Git仓库迁移实操(附批量迁移脚本)》,介绍他们将 GitLab 中一个 Group 内的几十个项目迁移到另一个 Group。
PS:文章有提到,前提是无法得到管理员协助,开启创建时导入的功能。

  1. git clone & git push && git push --tags
  2. git clone --mirror && git push --mirror
  3. git clone --bare && git push --mirror

基本方法就是 clone && push,不过参数不同。
只是,我没有了解过这里说的 --mirror 参数,这里记录一下,用到的时候研究研究。

文章带了两个脚本:

  • Linux migrate.sh
#!/bin/bash

remote_old=git@host1:group1
remote_new=git@host2:group2

while read repo
do
    echo $repo
    git clone --bare "$remote_old/${repo}.git"
    cd "${repo}.git"
    git push --mirror "$remote_new/${repo}.git"
    cd ..
    rm -fr "${repo}.git"
done < repos.txt
  • Windows migrate.bat
@echo off

set remote_old=git@host1:group1
set remote_new=git@host2:group2
set input_file=repos.txt

SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ %input_file%"`) do (
    call :process %%a
)
goto :eof

:process
SETLOCAL EnableDelayedExpansion
set "repo=!%1!"
set "repo=!repo:*:=!"
echo !repo!
git clone --bare "%remote_old%/!repo!.git"
cd "!repo!.git"
git push --mirror "%remote_new%/!repo!.git"
cd ..
rmdir "!repo!.git"
ENDLOCAL
goto :eof

#16 为什么 Git 这么不好用?

2023-01-10

看了一篇文章 What makes Git so hard to use? 在吐槽 Git 难用。

看完之后发现是软广,作者是想推荐自己公司的产品 HighFlux。我看了一下,似乎是通过封装和自动化来达到简化操作的目的。

我用 Git 几年了,不敢说熟练掌握,但是绝对可以说足以应付工作中的所有场景。

我逐条分析一下作者的观点:

Git commands are too many, too low-level and hard to understand.

作者认为,Git 有 157 个命令,让人觉得自己永远是初学者。

我的观点:只需要掌握常用的一些命令就够了,不需要了解那些底层命令。
底层命令是为其他的场景创造更多可能性。

但是确实可以改进一下:大部分人只需要关心十个左右的上层命令就行了,所以可以在产品上提供一些区分,比如分成 git-core / git-full。
好像也没啥意义,算了。

Git tracks 4 versions of files, instead of just "my" version and "the team's" version.

Git 管理文件的四种状态:除了本地版本,远程版本之外,还要学习 stash 和 index(staging area)。

我更加不敢苟同了,这应该正是 Git 强大的地方啊。

Stash 你不喜欢不用就是了。
Index 去掉似乎是可以少一个步骤,直接提交到本地仓库,对于非专业的人来说,减少一点点心智消耗。

sequenceDiagram
    WorkingDirectory ->> Index(StagingArea) : add
    Index(StagingArea) ->> LocalRepo : commit
    LocalRepo ->> RemoteRepo : push
    WorkingDirectory ->> + StashArea : stash
    StashArea ->> - WorkingDirectory : stash pop

Git doesn't let us safely experiment

作者说了三个功能的缺失:

  1. undo,就是所有操作的一个回退
  2. dryrun
  3. 丢失本地更新的操作,比如 git reset --hard 应该加一个确认

好像有点道理,对于非专业的人来说,这样是会友好些。
但是非专业的人是不是一般都用 GUI,这个事情 GUI 来做似乎完全没有问题啊!

我很少用 GUI 来执行什么操作(只使用 gitg 查看历史),所以对 Git GUI 生态不太了解。

这个意思是不是说 Git 缺少一个好用的 GUI?

#14 Git 命令

2021-08-04

看到有篇文章说是 git “新增”了 switch 和 restore 两个命令,仔细一看,原来就是 2019 年就引入了的两个命令,不过我确实没有用过。

这里重新整理一下现在 git 的命令。

git version
git version 2.30.2

apt list --installed | grep ^git
git-doc/hirsute,hirsute,now 1:2.30.2-1ubuntu1 all [已安装]
git-extras/hirsute,hirsute,now 6.1.0-1 all [已安装]
git-flow/hirsute,hirsute,now 1.12.3-1 all [已安装]
git-man/hirsute,hirsute,now 1:2.30.2-1ubuntu1 all [已安装,自动]
git-svn/hirsute,hirsute,now 1:2.30.2-1ubuntu1 all [已安装]
git/hirsute,now 1:2.30.2-1ubuntu1 amd64 [已安装]
gitg/hirsute,now 3.32.1-1 amd64 [已安装]
gitk/hirsute,hirsute,now 1:2.30.2-1ubuntu1 all [已安装]

#13 使用 git push --force-with-lease 替代 git push --force

2021-07-05

今天注意到了 git push 的一个参数 --force-with-lease,可以在 Remote 有更新的时候不执行强推。
我之前考虑过会有这样的情况发生:我准备强推之前,会做最后一次拉代码检查,无误之后 force push。但是这个检查和 push 之间有一个时间差,会不会在这期间有别的小可爱提交了代码呢?
这种情况是完全可能存在的,就像是线程安全问题,只是团队的规模消减了我对这种情况的担心。
但是 --force-with-lease 参数可以彻底化解我的这种担忧,我决定以后就改用这个参数了。

#12 Git 分支管理策略(工作流)

2021-04-07

Git Logo

Git Flow

荷兰程序员 Vincent Driessen 2010 年提出。

Git Flow
PDF 下载

  • master 主干
  • develop 开发分支
  • feature/xxx 功能开发分支(临时)
    基于 develop 创建,开发完成之后:合并到 develop 分支,删除
  • release/xxx 预发布分支(临时)
    基于 develop 创建,测试通过之后:合并到 master 分支,打 tag,合并到 develop 分支,删除
  • hotfix/xxx 问题修复分支(临时)
    基于 master 创建,问题修复之后:合并到 master 分支,打 tag,合并到 develop 分支,删除

特点:基于版本交付

PS: 作者于 10 年后,也就是 2020 年,更新了一次,表示:对于互联网应用的开发应该考虑更加简单的工作流,比如 GitHub Flow。但不管怎样,应该结合自身的实际情况,不能盲目照搬。

GitHub Flow

GitHub Flow

  1. 从 master 拉分支,提交,推送
  2. pull request
  3. 评审,测试
  4. merge 到 master

特点:基本不涉及项目的分支管理,主要是对多人协作方式提出建议:Pull Request。适合多人参与的开源项目,由项目管理员负责维护主干。

中间可以借助自动化工具来静态分析、部署、测试,提升开发速度。但这些工具不是 GitHub Flow 专有,或者说不是它的特色。

这套逻辑看似非常简单,但要硬套到企业项目开发流程中可能会非常复杂,水土不服。
PS: 虽然 git 新增了一个 request-pull 子命令,但可能很鸡肋,不可能脱离 Web 来参与讨论、评审代码。

GitLab Flow

GitLab Flow

分不同环境:

  • master 开发分支,管理方式就是 GitHub Flow,不过就是 Pull Request 改名为了 Merge Request
  • pre-production 预发布分支,只能从 master 合并
  • production 发布分支,只能从 pre-production 合并

如果需要发布:

  1. 从 master 拉分支,比如:20-04-stable,创建语义化版本号。
  2. 如果后期有严重 BUG,可以从 master cherry-pick 过来。

特点:比 GitHub Flow 更进一步,对项目的发布和部署提出了建议,并支持多个环境。

主要是其中有一点特别好的就是: Upstream First, 上游优先。所有环境以及维护分支的提交必须来自 master 分支。

我的思考

当然,还是那句老话:适合自己的就是最好的。
项目分支管理流程要和项目自身的特点,以及团队成员的技术水平相匹配。

Git Flow 的整套流程挺完备的,符合一般开发的习惯,只是对其作出规范而已。
GitHub Flow 也好,GitLab Flow 也好,都可以看做是 Git Flow 的补充。

GitHub Flow 和 GitLab Flow 都假定 master 分支是可发布的,而 Git Flow 从 master 拆分出了一个 develop 作为缓冲,我认为这个设计比较合理。

Git Flow 有几个需要注意的问题:

  1. 合并的时候保留之前的合并记录,谨慎快进 (--no-ff)
  2. hotfix, release 分支推送到 master 发布之后,切记还要同步推送到 develop 分支
  3. 必须坚持 master, develop 上不随意推送(还是得靠 Pull Request 机制)
  4. 如果有不属于当前发布周期需要的开发,不要合并到 develop
  5. 临时分支必须快用快销,不要长时间保留,且合并之后理解删除

我设想中的开发流程

1,基本参照 Git Flow (借助工具)

上游优先原则:master 分支作为所有可发布环境的上游

2,自动化测试:

  • develop, release, master: 只要有变更就触发一次自动化测试
  • 此外, master 应该保持一定频率的定时自动化测试

3,老版本需要维护就在 tag 上拉分支。

现实场景中,可能要为 abc 环境上的某个老版本 v1.0.0 修复 BUG、加功能,或对已有功能进行一些调整。

git branch maintain/abc v1.0.0 # 一旦分叉,就需要长期保留该分支
# maintain/abc/develop
# maintain/abc/feature/xxx
# maintain/abc/hotfix/xxx
# maintain/abc/release/xxx
# 视情况,可以简化处理,不用上面这些分支

PS: 最后需要重新发布的时候可以对版本号加上附加的标识 v1.0.0.1.abc

5,如果是 OEM,针对客户有关的信息、资源应该留给打包系统来统一处理

此外:

  1. 项目应有明确的 roadmap
  2. 代码评审
  3. 数据库设计统一管理
  4. 项目文档,需求库,用例库
  5. 版本号基本上遵循语义化版本规范
  6. 提交记录遵循 git commit message 规范 (借助工具)
  7. CI/CD + 自动化测试

参考资料与拓展阅读

#11 Git 分支管理

2020-07-16

创建分支:

git branch <new-branch-name> <commit-id>
git checkout -b <new-branch-name> <commit-id>

删除远程分支:

git push --delete origin dev0404

删除远程已经不存在的分支:

git remote prune origin -n
git remote prune origin

已经合并到指定分支的分支:

git branch --merged master
# -r, --remote
git branch -r --merged master

创建独立分支(空白分支):

git checkout --orphan newbr

合并无关分支:

git merge newbr --allow-unrelated-histories

#10 在 Git 历史记录中搜索

2020-06-12

搜索提交信息

git log --grep=fix: --oneline --after='2018-07-01' --author=markjour

搜索历史文件

git grep -C3 sign_position $(git rev-list --all)

搜索 diff 内容

git log -G'前置'
git log -G'前置' -p | grep '前置' -C5
git log -G'前置' --oneline --name-status

-S<string> --pickaxe-regex-G<regex> 作用相近,
不过 -S 只会列出搜索内容增删的相关信息,也就是所在行修改了,但是搜索内容没有变化的会忽略