背景

原生Centos7系统的yum源自带git版本是1.8.3.1。

这个版本诞生于:10-Jun-2013。

很多新特性都不支持,为了更好的使用git,我们需要进行版本升级。

源码编译安装

  1. 安装相关依赖
    1
    2
    # yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel asciidoc
    # yum install gcc perl-ExtUtils-MakeMaker
  2. 卸载当前git
    1
    # yum remove git
  3. 下载新版本源码包
    1
    2
    3
    4
    官方仓库地址:https://mirrors.edge.kernel.org/pub/software/scm/git/
    当前最新版本:git-2.28.0.tar.xz 27-Jul-2020

    # wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.28.0.tar.xz
  4. 源码编译安装
    1
    2
    3
    4
    5
    6
    7
    8
    # tar -xvf git-2.28.0.tar.xz
    # cd git-2.28.0/
    # which openssl 获取本机openssl路径,当前机器/usr/bin/openssl
    # ./configure --with-openssl=/usr/bin/openssl
    # make prefix=/usr/local/git all
    # make prefix=/usr/local/git install
    # echo "export PATH=$PATH:/usr/local/git/bin" >> /etc/profile
    # source /etc/profile

Comment and share

Git tips two

in SCM

软件版本:

1
git version 2.23.0

使用http/https协议代码库地址,有时会出现不能存储密码,每次交互操作都需要输入帐户密码情况:

1
2
3
记住密码(默认15分钟):git config --global credential.helper cache
自己定义时间(一小时后失效):git config credential.helper 'cache --timeout=3600'
永久存储密码:git config --global credential.helper store

行结束符处理:

OS Line Endings Comments
Windows CRLF 每行结尾是 <换行><回车 > ,即 \n\r
Mac OS X LF 每行结尾只有 <换行> ,即 \n
Unix/Linux LF 每行结尾只有 <换行> ,即 \n
Classic macOS CR 每行结尾是 <回车>,即 \r
1
2
3
4
5
6
7
8
9
10
11
排除老Mac系统不讨论,项目组如果不是全Windows环境开发/部署的话,还是要自动处理下行结束符。

# Windows用户执行下面配置命令:
$ git config --global core.autocrlf true # 在提交时自动地把行结束符CRLF转换成LF,而在签出代码时把LF转换成CRLF

# Linux 和 Mac用户执行下面配置命令:(预防代码库已经有CRLF结束符的代码)
$ git config --global core.autocrlf input # 在提交时把CRLF转换成LF,签出时不转换

# 默认配置:
$ git config --global core.autocrlf false # 提交和签出时都不对代码行结束符做转换

Comment and share

参考链接:


场景1:

最新的一个提交版本里面新增了敏感、较大、无意义的文件,需要进行清理。
1
2
3
4
5
6
7
8
9
10
11
1. 删除文件
$ git rm --cached ${文件绝对地址}
2. 增加到上述文件到 .gitignore
$ vim .gitignore
3. 修复最新提交版本
$ git commit --amend
4. 推送新版本到远端仓库
如果刚才版本已经推送到远端仓库:
$ git push -f
如果刚才版本只是在本地仓库:
$ git push

场景2:

历史版本里面存在敏感、较大、无意义的文件,需要进行清理。

使用 git filter-branch

git 原生提供的命令,如果没有的话,请先升级机器git版本。

  • 原理:
    扫描代码库所有版本
    如果某个版本里面发现了指定的文件OR目录:
    如果此版本包含要清理的文件OR目录 和 其它变更的话,对此版本进行删除指定文件OR目录(保留其它变更),并生成新的版本。同时后面的版本会变基到新版本。
    如果此版本只包含要清理的文件OR目录变更的话,那么此版本会被清除。同时后面的版本会变基到上一个版本。
    如果版本没有包含指定文件OR目录,那么继续遍历。
  • PS:
    1. 如果代码库历史比较多 OR 涉及到指定文件OR目录的版本比较多,那么命令执行会比较慢。
    2. 一般会导致代码库版本树变化,对于涉及开发同学,建议开始前提交本地修改变更到远端仓库,完成后本机重新clone代码库进行开发。
    3. 一般都在本地仓库根目录执行
    4. 执行命令后历史版本里面已经清理了文件, 但是我们的本地仓库里面仍然保留了这些objects, 等待垃圾回收(GC), 如果想立即回收本地仓库空间可以执行 git gc –prune=now.
1
2
3
4
5
6
7
8
9
10
1. 执行命令
$ git filter-branch --force --index-filter 'git rm --cached -r --ignore-unmatch ${要清理的文件OR目录的绝对地址}' --prune-empty --tag-name-filter cat -- --all
2. 增加到上述文件OR目录到 .gitignore
$ vim .gitignore
3. 推送新版本到远端仓库
$ git push -f --all
$ git push -f --tags
4. 清理本地仓库残留的git objects
$ git reflog expire --expire=now --all
$ git gc --prune=now

使用 bfg-repo-cleaner

Roberto Tyley使用Scala语言写了 bfg-repo-cleaner工具。
可以简单理解为一个轻量级的 git filter-branch。
使用比较简单,功能比较强大,只需要下载最新的jar包,然后执行👇命令:

1
2
3
4
# 删除大于50M的文件
$ java -jar bfg.jar --no-blob-protection --strip-blobs-bigger-than 50M
# 删除指定文件
$ java -jar bfg.jar --no-blob-protection --delete-files ${要清理的文件的绝对地址}

PS:
1. bfg-repo-cleaner 有个protect功能,默认HEAD是受保护的。
受保护的分支最新版本如果涉及需要清理文件,那么并不会成功。
–no-blob-protection 关闭protect功能
–protect-blobs-from ${分支1},${分支2} 增加受保护的分支
2. 建议在本地仓库根目录执行。


场景3:

查找代码库里面较大文件方法:
- 如果当前版本还存在的文件,可以直接du排序来识别;
- 如果当前版本不存在,但是历史中出现过的大文件,可以按照下面步骤来查询。

1
2
1. 显示比较大的pack
$ du -ah .git/objects/pack

logo

1
2
2. 识别object,对输出的第三列信息即文件大小进行排序
$ git verify-pack -v .git/objects/pack/${pack-XXX.pack} | sort -k 3 -n | tail -5

logo

1
2
3. 识别object对应的文件
$ git rev-list --objects --all | grep ${👆获取的object}

logo

Comment and share

背景:

公司主要使用git作为代码管理仓库,现需要把部分使用svn管理的代码迁移到git。

需求:

需要保留所有 branches、主干、tags的历史记录。

迁移方法:

使用git官方提供的git svn命令

系统环境:

  • OS: macOS 10.13.3
  • SVN:1.9.4
  • GIT:2.16.2

迁移步骤:

  1. 获取指定svn代码库涉及的开发同学名单并转换:
    svn log $SVN_URL –xml | grep author | sort -u | perl -pe ‘s/.>(.?)<.*/$1 = /‘ > user.txt

user.txt内容如下:
dev1_name =
dev2_name =
因为svn只有用户名,而git需要提供用户名和邮箱,所以我们需要做下用户转换。
修改上述命令得到的user.txt如下:
dev1_name = dev1_name
dev2_name = dev2_name
2. 使用git svn cloned代码库到本地:
git svn clone $SVN_URL –no-metadata –authors-file=user.txt -s
3. 调整本地库目录结构:
cd $project_dir
mv .git/refs/remotes/origin/tags/$tags_name .git/refs/tags/
mv .git/refs/remotes/origin/$branches_name .git/refs/heads/
rm -rf .git/refs/remotes/origin
4. 上传本地库到remote仓库:
git remote add origin $GIT_URL
git push origin –all
git push origin –tags

PS:

  1. 如果svn历史记录太多,而且并不需要很久之前的版本的话,可以选择从指定版本进行转换。
    git svn clone $SVN_URL -r $指定版本:HEAD
  2. 较新版本的git都原生带了 git svn命令,如果你使用的git版本没有此命令,建议升级新版git或者单独安装git-svn命令。
  3. git clone命令执行时间主要和 原SVN库大小、log多少有关。
  4. svn迁移git后需要注意git不支持空目录,需要使用在空目录增加隐藏文件来上传,通常使用.gitkeep文件。
  5. 如果原SVN库结构不是规范的branches、tags、trunk结构
    git svn clone $SVN_URL –branches= –tags= –trunk=
    如果没有tags的话–tags可以不写,branches同理;subdir写相对路径即可
    上面使用的-s参数表示的是–stdlayout适合标准结构的SVN项目。

Comment and share

分支策略

in SCM

背景:

为了更好的支持产品研发过程,我们需要设计符合公司研发的分支策略。
无论多复杂或者简单的策略都可以归类为以下两种:

1.主干开发,分支发布
2.分支开发,主干发布

PS:我们约定:

主干(master/git trunk/svn)
分支(branch)
标签(tag)
如果从版本控制工具实现上来看:
svn: trunk、branch、tag 没有差别
git: master、branch、轻量级tag 没有差别
为了更好的区分和管理,人为的从逻辑上进行区分
tag的作用:里程碑记录,方便回溯(发布回滚等)

主干开发,分支发布:

logo

  • 优点:
    1. 较少的分支存在,大家专注在主干开发
  • 适用于:
    1. 敏捷开发模式,每个迭代都很快
    2. 维护型项目,较少需求变更,基本没有并行开发的需要
    3. 个人项目
  • 常用方式:
    1. 所有dev在主干上面进行开发
    2. 需要发布的时候从指定版本拉出发布分支,进行测试
      • 如果成功:那么打出tag,进行发布
      • 如果不成功:那么继续在发布分支上面进行修改,然后测试;
        测试成功后,打tag,合并发布分支修改到主干;

分支开发,主干发布:

logo

  • 优点:
    1. 对并行开发支持很好
  • 适用于:
    1. 并行开发很频繁的项目
  • 常用方式:
    1. 根据项目发布排期拉出并行开发分支
    2. 不同or相同的dev分别在分支上面进行开发
    3. 测试通过后,打tag进行发布,合并分支修改到主干
    4. 后发布的分支需要合并最新的主干代码
  • 注意点:
    1. 所有分支都从主干拉出;
    2. 发布时候要检查 tag是否包含最新的主干代码;
    3. 后发布的分支在合并最新主干代码后,注意测试范围扩大(除了测试本分支功能外,合并过来的功能也需要覆盖到!!!)

PS:

本文只是简单介绍下基础的分支策略,各位需根据自身团队、业务来综合定制适合的分支策略。

Comment and share

Git tips one

in SCM

软件版本:

1
git version 2.10.1

Git克隆单个分支:

1
2
3
4
5
6
7
8
9
$ git clone 地址 —branch br1 —single-branch dir
只能看到单独的br1,不能checkout到其他分支。空间占用比较小,适合长期分支开发。
原理:
$ git remote -v
remote.origin.fetch=+refs/heads/br1:refs/remotes/origin/br1
恢复完整代码库:
$ git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
然后执行
$ git pull

Git对.gitignore文件处理:

1
2
3
4
5
6
已经增加到.gitignore文件里面的目录or文件会被git忽略。
如果本次需要修改一个忽略文件:
$ git status --ignored
--ignored -- show ignored files as well
$ git add -f
--force -f -- allow adding otherwise ignored files

Git commit相关:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 空提交,只在特殊情况下使用(产生一个新的commit点)
$ git commit
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean
# 解决方法
$ git commit -m "empty commit" --allow-empty


# 不带message提交(慎用,message很重要)
$ git commit
Aborting commit due to empty commit message.
# 解决方法
$ git commit --allow-empty-message


把暂存区的变更合并到最新的版本里面,不会产生新的版本(同时可以更新log message);
$ git commit --amend
PS:已经进远端代码库的版本不允许使用--amend进行修改!!!

Git merge相关:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
conflict处理:
# 使用自己/他人的文件替换冲突文件
$ git checkout --ours conflict.file
$ git checkout --theirs conflict.file
# 增加冲突文件到版本库
$ git add conflict.file
$ git commit


查看merge commit点已经解决的冲突文件:
$ git log --cc
--cc -- combined diff format for merge commits


分支直接合并建议使用:git merge
同一分支dev合并 or Temp分支合并建议使用:git rebase 或者 git cherry-pick
PS:以上两种都可以合并代码workspace最终文件一样,但是对git来说有不同:merge是环形,rebase和cherry-pick是直线
PS:需要注意的是rebase会是自己和他人角色发生反转,解决conflict file的时候需要留心。

Git rm相关:

1
2
3
4
5
$ git rm weilong.txt
删除workspace和index里面的weilong.txt文件

$ git rm --cached weilong.txt
删除index里面的weilong.txt文件,workspace里面的文件保留

Git log相关:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ git log -5
查看最新的5次版本

$ git log --author=weilong.wang
查看weilong.wang提交的版本

$ git log --oneline
一行显示一个版本信息(简化显示版本信息)

$ git log -p
显示每个版本的具体修改

$ git log --numstat
显示每个版本 修改文件的行数(5 1 weilong.txt 这个文件本次增加了5行同时也删除了1行)

$ git log --since="1 month ago"
显示最近一个月的日志
$ git log --after="2016-07-01"
显示7月1号至今的日志
$ git log --before="2 days"
显示2天之前的日志
$ git log --until="2016-07-10T14:30"
显示7月10号14:30之前的日志


$ git log --graph
图状显示版本 (正常提交时线形的,merge是环形的)

可用于判断分支是否合并:
$ git log br1 ^master
显示只在分支br1不在master上的commit点
$ git log master ^br1
显示只在分支master不在br1分支上的commit点

logo

Comment and share

  • page 1 of 1
Author's picture

Weilong

    Write something about work-life:

PM


Shenzhen