GIT practices

Table of Contents

这篇文章主要根据《Pro Git 2nd》中文版来记录 GIT 的实践过程。

1 安装

sudo apt-get install -y git

2 起步

2.1 关于版本控制

2.2 Git 简史

2.3 Git 基础

2.3.1 Git 如何保存快照?快照多个部分的共同部分多次存放会不会导致文件系统过大?

2.3.2 Git 文件恢复原理

2.4 命令行

2.5 安装 Git

2.6 初次运行 Git 前的配置

2.7 获取帮助

2.8 总结

3 Git 基础

3.1 获取 Git 仓库

3.1.1 git init 与 git init –bare 的区别?

3.2 记录每次更新到仓库

3.2.1 differ 格式1

3.2.2 使用 Beyond Compare2

3.3 查看提交历史

3.3.1 git windows 下提交 comment 乱码问题

3.4 撤销操作

4 Git 分支

5 服务器上的 git

需求:在 VPS 有一个 Git Server 来保存一些私有项目,并不打算进行进行分享或者进行复杂的编辑,如拉分支等。

方案:

  • 使用 git 官网介绍的方法搭建 ssh 链接的 server。

    git init --bare private-projects.git
    

    配置 ssh

    mkdir ~/.ssh
    cd ~/.ssh
    touch authorized_keys
    

然后把开发者的私钥添加要这个 authorized_keys 当中。

  • 使用 GitLab。

    GitLab 支持私人仓库,可以直接使用。

  • 使用 Bitbucket
mkdr private-projects
cd private-projects
git --bare init

6 分布式 Git

7 GitHub

8 Git 工具

8.1 子模块

8.1.1 添加

8.1.2 删除

  • 删除 .gitsubmodule 中对应 submodule 的条目
  • 删除 .git/config 中对应 submodule 的条目
  • 执行 git rm –cached {submodule_path}。注意,路径不要加后面的 “/”。例如:你的 submodule 保存在 supports/libs/websocket/ 目录。执行命令为:git rm –cached supports/libs/websocket

8.1.3 更新

  • 更新 .gitsubmodule 中对应 submodule 的条目 URL
  • 更新 .git/config 中对应 submodule 的条目的 URL
  • 执行 git submodule sync

9 自定义 Git

10 Git 与其他系统

10.1 作为客户端的 Git

10.1.1 设置 git commit log 编码

10.1.2 windwos 下文件路径编码

10.2 迁移到 Git

这小节主要描述在公司如何代码库从 SVN 迁移到 Git,并保留原有的 commit log 信息,以及迁移过程中要注意的事情。迁移步骤:3

10.2.1 准备环境

需要安装对应的软件:

sudo aptitude install -y git Subversion git-svn

10.2.2 规范 Subversion4

确认项目的 Subversion 地址:https://scms.example.com/svn/projects/west/

后面统一用 $PROJECT 表示项目的 Subversion 地址。

规范项目在 Subversion 的目录结构包含 trunk、branches、tags

  • branches 和 tags 目录下的分支和标签保持平级,例如:
    • tags/v1.0.0 可以。
    • tags/1.x/v1.0.0 多了层目录就不可以。
  • 如果不是平级,以 tags 为例,先执行 svn mv 操作
    • 方式 1 - 远程 svn mv

       svn mv $PROJECT/tags/1.x/v1.0.0 $PROJECT/tags/v1.0.0
      
    • 方式 2 - 本地 svn mv

       svn co $PROJECT west_subversion
       cd west_subversion
       svn mv tags/1.x/v1.0.0 tags/v1.0.0
      

最后规范后的目录示例如下:

west
├── trunk
│   ├── docs
│   ├── west
│   ├── setup.py
│   └── README.rst
├── branches
│   ├── hotfix_add_user_error
│   ├── hotfix_issuse_9527
│   ├── feature_unittest4app
│   └── feature_multi_add_user
└── tags
    ├── v1.0.0
    ├── v1.0.1
    ├── v2.0.0
    └── v2.1.0

10.2.3 生成提交者 ID 和邮箱

在 Subversion 中,每一个人提交时都需要在系统中有一个用户,它会被记录在提交信息内。 如果想要将 Subversion 用户映射到一个更好的 Git 作者数据中,需要一个 Subversion 用户到 Git 用户的映射。 创建一个 users.txt 的文件包含像下面这种格式的映射:

   user1 = First Last Name <email@address.com>

为了获得 SVN 使用的作者名字列表,可以运行:

   svn log --xml | grep author | sort -u |  perl -pe 's/.*>(.*?)<.*/$1 = /' > user.txt

这会将日志输出为 XML 格式,然后保留作者信息行、去除重复、去除 XML 标记。 (很显然这只会在安装了 grep、sort 与 perl 的机器上运行。) 然后,将输出重定向到你的 users.txt 文件中,这样就可以在每一个记录后面加入对应的 Git 用户数据。 我们项目中 实际执行完以后,发现文档中每行格式是这样的:

   user1 =

猜测可能 svn 中没有保留对应的邮箱地址,需要我们来补全,而且,作为第一个迁出项目的人,最好把邮箱地址都换成自己的,这样在后面向 git 提交的时候不会遇到下面的权限问题:

remote: ERROR: In commit 34f414c0ae5dcb8619c7cb568181f9dfa3ccf840
remote: ERROR: committer email address yanliang@xunlei.com
remote: ERROR: does not match your user account.
remote: ERROR:
remote: ERROR: The following addresses are currently registered:
remote: ERROR: liushangliang@xunlei.com
remote: ERROR:
remote: ERROR: To register an email address, please visit:
remote: ERROR: http://10.10.164.250:8080/#/settings/contact

你可以将此文件提供给 git svn 来帮助它更加精确地映射作者数据。 也可以通过传递 --no-metadata 给 clone 与 init 命令,告诉 git svn 不要包括 Subversion 通常会导入的元数据。 迁出项目代码(git-svn)

   git svn clone --authors-file=users.txt --no-metadata --stdlayout http://10.10.16.252/code_svn/xl_vip/vip_lixian/trunk/downloader/ris/  des-dir
  • --authors-file 是得到的 git log 提交记录映射好提交者的信息
  • --no-metadata 是得到的 git log 不带上对应的 Subversion 信息了,更干净
  • --stdlayout 是先前准备的按规范目录风格来迁出代码 这样就得到一个已经导入了分支与标签的有效的 Git 仓库。如果出现用户名没有找到,需要更新 user.txt 文件,然后

    cd des-dir
    git svn fetch
    

    如果项目比较大,可能需要重复上面的命令好几次,知道所有的 svn commit 全被抓取下来。 完成后,svn 的所有 trunk 会被当做新的 git branch,可以通过 git branch -r 进行查看。

    svn tags 也会当做 branch 导入。

10.2.4 转化成 Git 仓库格式

应当做一些导入后的清理工作。 第一步,你应当清理 git svn 设置的奇怪的引用。 首先移动标签,这样它们就是标签而不是奇怪的远程引用,然后你会移动剩余的分支这样它们就是本地的了。 为了将标签变为合适的 Git 标签,运行

  cp -Rf .git/refs/remotes/tags/* .git/refs/tags/
  rm -Rf .git/refs/remotes/tags/

这会使原来在 remotes/origin/tags/ 里的远程分支引用变成真正的(轻量)标签。

接下来,将 refs/remotes 下剩余的引用移动为本地分支:

  cp -Rf .git/refs/remotes/* .git/refs/heads/
  rm -Rf .git/refs/remotes/

现在所有的旧分支都是真正的 Git 分支,并且所有的旧标签都是真正的 Git 标签。下一步是一个将你的服务器添加为远程仓库。

10.2.5 添加远程仓库

git remote add gerrit gerrit:xl_lixian_ris.git

10.2.6 传所有分支与标签5

git push gerrit --all
git push gerrit --tags

现在通过以上漂亮、干净地导入操作,所有分支与标签都应该在新 Git 服务器上。

11 Git 内部原理

12 Tips

12.2 使用 bcompare 作为 diff、merge 工具6

Beyond Compare 官网上的版本目前是 4.+ 版本, 下载直接安装即可。

检查 git 的版本, 根据版本的不同选不同的方法进行设置, 本文是基于 Git 2.3+ 版本操作, 2.3 以下的版本可以参考 Beyond Compare 官网上的其他版本控制配置方法。7

12.2.1 Diff

切换到终端:

git config --global diff.tool bc3

当需要比较修改的时候, 在终端中直接输入 git difftool file.ext 就可以唤起 Beyond Compare。

12.2.2 Merge

切换到终端:

git config --global merge.tool bc3
git config --global mergetool.bc3 trustExitCode true

当代码发生冲突的时候, 在终端中使用 git mergetool <conflict file> 即可唤起 Beyond Compare, 可谓是十分强大.

12.2.3 beyondCompareMerge

注意在使用 git megetool 来解决冲突后, 会生成 备份文件 (*.orig), 大多数情况下不是我们想要的, 在终端中配置:

git config --global mergetool.keepBackup false

这样就不会每次在解决冲突后生成对应的 .orig 文件了.

12.2.4 中文路径乱码

git config --global core.quotepath false

Footnotes:

Author: lsl

Created: 2016-08-07 Sun 19:48

Validate