返回介绍

4 进阶篇

发布于 2024-09-08 19:20:07 字数 11433 浏览 0 评论 0 收藏 0

4.1 团队协同开发

4.1.1 账号权限管理

要求:团队里的每个人都对仓库有写权限,又不能给每个人在服务器上建立账户. 那么提供 SSH 连接就是唯一的选择了。

方法 1: 是给每个人建立一个账户,直截了当但过于繁琐。反复的运行 adduser 并且给所有人设定临时密码可不是好玩的。

方法 2: 是在主机上建立一个 git 账户,让每个需要写权限的人发送一个 SSH 公钥,然后将其加入 git 账户的 ~/.ssh /authorized_keys 文件。这样一来,所有人都将通过 git 账户访问主机。这丝毫不会影响提交的数据——访问主机用的身份不会影响 commit 的记录。

方法 3: 是让 SSH 服务器通过某个 LDAP 服务,或者其他已经设定好的集中授权机制,来进行授权。只要每个人都能获得主机的 shell 访问权,任何可用的 SSH 授权机制都能达到相同效果。

方法 2 的详细步骤

  1. 产生公钥
ssh-keygen -C "你的 email 地址" -t rsa

该命令将生成一对非对称的公\私密钥,默认它们被存储在:

  • XP/2003 用户: c:\Documents and Settings\登陆名\.ssh
  • Vista 用户: c:\Users\登陆名\.ssh
  • linux: ~/.ssh
  1. 在 linux 服务器上将公钥加到 git 用户的 authorized_keys 文件中。

类似工具 :使用 Gitosis 的多用户访问

在 gitosis 中,有一个叫 authorized_keys 的文件,里面包括了所有授权可以访问仓库的用户的公钥(public key), 这样每个用户就可以直接使用'git'用户来推送(push) 和拉(pull) 代码。

安装与配置 Gitosis (英文)

译者注 1: github.com 就是采用这种方式来配置私有(仓库) 访问。

译者注 2: Gitosis 配置(中文)

4.1.2 开源协同开发

示例: git@github.com :looly/elasticsearch-definitive-guide-cn.git

开始我对 Pull Request 流程不熟悉,后来参考了 @numbbbbb 的《The Swift Programming Language》协作流程,在此感谢。

  1. 首先 fork 我的项目
  2. 把 fork 过去的项目也就是你的项目 clone 到你的本地
  3. 运行 git remote add looly [git@github.com](mailto:git@github.com):looly/elasticsearch-definitive-guide-cn.git 把我的库添加为远端库
  4. 运行 git pull looly master 拉取并合并到本地
  5. 翻译内容
  6. commit 后 push 到自己的库(git push origin master)
  7. 登录 Github 在你首页可以看到一个 pull request 按钮,点击它,填写一些说明信息,然后提交即可。

1-3 是初始化操作,执行一次即可。在翻译前必须执行第 4 步同步我的库(这样避免冲突),然后执行 5-7 既可。

4.2 分支 branch 和 tag 管理

版本号:x.x.x=主版本号.次版本号.发布序列。主版本号只用在重要架构级或功能大升级。

表格 branch 和 tag 比较表

 说明主要命令
tag 标签组成为 vx.x.x,完整的版本号,用来标识阶段性的发布版本(不再编辑的分支),
相当于 release-x.x.x git push --tags #推送全部 tag
git push origin [xxx] #推送单个 tag 到远程
git push origin -d [xxx] #删除远程指定 tag
git tag # 查看 git tag -a [xxx] # 打 tag git tag -d [xxx] #删除本地指定 tag
branch 分支组成为 x.x,其中含义两个固定分支 master 和 devel。
如果项目不是太复杂,devel 分支将取代所有版本分支。
# 查看远程分支,查看本地不用 -a
$ git branch -a
$ git push origin [xxx] # 推送分支到远程
$ git push origin :[xxx] # 删除远程分支,或者将:改为--delete
# 创建分支
git checkout --orphan [空分支]
git checkout -b [to] [from]
git branch -d [xxx] #删除分支
git checkout [xxx] #切换分支
git merge [to] #合并分支
git branch -m [old] [new] # 重命名分支

备注:命令参数如-d/-D 大小写不敏感。tag 和 branch 推送远程的操作命令类似。

image-20191208223108973

图 2 git 客户端里的 revision graph

说明 :最下面 e35a6b9 是仓库第一个 commit 的 SHA-1 值,黄色字体 v1.0.0/v1.1.0 是 tag,蓝色字体 master/develop 是远程分支,红色字体 distributed 是本地当前分支。带有 origin 前缀的都是远程分支。理论上 tag 要一直保持在 master 分支里。

4.2.1 分支管理策略

分支名称使用场合注意事项
主分支 master所有提供给用户使用的正式版本,都在这个主分支上发布。用来分布重大版本。 
开发分支 develop日常开发。 包括创建分支、切换分支和合并分支。gitcheckout−bdevelopmastergit checkout -b develop mastergitcheckout−bdevelopmaster git checkout master
$ git merge --no-ff develop
临时性分支用于应对一些特定目的的版本开发。如
* 功能(feature)分支~ feature-*
* 预发布(release)分支~ release-*
* 修补 bug(fixbug)分支~ fixbug-*
feature/release 从 develop 分支分出,fixbug 从 master 分支分出。
临时性分支合并到 develop 分支后可删除。
release 和 fixbug 分支合并到 master 后可打 tag。

备注:tag 需从 master 打,标识为 vx.x.x,如 v1.2.0

1. 主分支 Master

首先,代码库应该有一个、且仅有一个主分支。所有提供给用户使用的正式版本,都在这个主分支上发布。

2. 开发分支 Develop

主分支只用来分布重大版本,日常开发应该在另一条分支上完成。我们把开发用的分支,叫做 Develop。这个分支可以用来生成代码的最新隔夜版本 (nightly)。如果想正式对外发布,就在 Master 分支上,对 Develop 分支进行 合并(merge)。(备注:被 master 合并分布后,也可以反向合并 master 或从其它分支获取修改,进行下一步的修改)

# 创建分支:Git 创建 Develop 分支的命令
$ git checkout -b develop master

# 切换分支:将 Develop 分支发布到 Master 分支的命令
$ git checkout master
# 对 Develop 分支进行合并,缺省合并是快进式合并~即将 master 直接指向 develop
# -no-ff 参数会执行正常合并,在 Master 分支上生成一个新节点。推荐使用-no-ff,可以保持演进的清晰(被合并分支 develop 会多一个指向 master 某 commit 的节点)。
# 若 develop 的修改未提交到远程,就合并到本地 master,那么合并后 develop 远程分支并不会出现修改部分,这样会造成 develop 与 master 并不同步,在进行 develop 开发前建议先同步远程 master(会增加很多来自 master 的 commit log)。develop 开发前根据需要从不同的远程分支更新内容,develop 本身的日志基本无意义。
$ git merge --no-ff develop

3. 临时性分支

临时性分支,用于应对一些特定目的的版本开发,开发合并后可以删除此分支。临时性分支主要有三种:

  • 功能(feature)分支,为了开发某种特定功能,从 develop 分支分出。feature 分支开发完需合并到 develop。
  • 预发布(release)分支,develop 合并到 master 之前提供的测试分支,从 develop 分支分出。
  • 修补 bug(fixbug)分支,从 Master 分支上面分出来的。relaese/fixub 分支开发完需合并进 Master 和 Develop 分支,合并到 master 后可以打 tag。

示例 1:修补 bug 分支 fixbug-x 流程(从 master 创建,合并到 maste 打 tag,再合并到 devel 删除分支)。

# 创建分支 fixbug-x
$ git checkout -b fixbug-x master
# 合并到 master 分支,并 tag
$ git checkout master
$ git merge --no-ff master
$ git tag -a v1.2.2

# 合并到 devel 分支,并删除分支
$ git checkout devel
$ git merge --no-ff devel
$ git branch -d bugfix-x

4.2.2 分支管理实例

1) 本地管理分支

# create branch, branch_name default: local
$ git branch [branch_name]
# switch to branch
$ git checkout [branch_name]

# merge branch,将 branch_name 合并到当前分支
$ git merge [branch_name]
# delete branch
$ git branch –D [branch_name]

2) 分支协同开发

a) 首先在本地产生 branch, 工作过后,将本地 branch 合并到本地 master.
b) git pull 取其它成员的工作树到本地,如果有修改,将自动合并到本地 master
c) git push 将本地 master 分支更新到远程服务器。

4.3 子模块 submodule

Git 子模块(submodule)是一个强大的功能,用于在一个 Git 仓库中包含另一个 Git 仓库。它允许你将一个项目作为另一个项目的子目录进行管理。子模块常用于将依赖库或第三方代码集成到你的项目中,而无需将它们的代码直接合并到主项目中。

核心概念

  1. 子模块

    • 子模块是一个 Git 仓库,它被嵌套在另一个 Git 仓库的子目录中。主仓库跟踪子模块的特定版本,而不是子模块的最新版本。
  2. 引用

    • 主仓库存储子模块的 URL 和特定的提交 ID。每当子模块更新时,主仓库需要更新引用以跟踪子模块的新版本。
  3. 隔离性

    • 子模块与主仓库的内容独立管理,允许你单独更新和管理子模块中的代码。

常用命令

  1. 添加子模块

    • git submodule add <repository> [<path>]
      • 将指定的 Git 仓库作为子模块添加到主仓库中。如果未指定 <path> ,则使用仓库名作为路径。
    git submodule add https://github.com/example/libfoo.git libfoo
    
  2. 初始化子模块

    • git submodule init
      • 初始化 .gitmodules 文件中列出的子模块。这会在本地工作目录中创建子模块目录,但不会自动更新内容。
    git submodule init
    
  3. 更新子模块

    • git submodule update
      • 将子模块的内容更新到主仓库中指定的提交 ID。这个命令会检出子模块的正确版本。
    git submodule update
    
  4. 克隆包含子模块的仓库

    • git clone --recurse-submodules <repository>
      • 克隆主仓库及其子模块。如果子模块不在克隆过程中自动初始化和更新,可以使用 git submodule update --init --recursive 进行更新。
    git clone --recurse-submodules https://github.com/example/myrepo.git
    
  5. 查看子模块状态

    • git submodule status
      • 查看子模块的当前状态,包括当前提交 ID 和是否有任何未提交的更改。
    git submodule status
    
  6. 更新子模块到最新提交

    • cd <submodule-path>
    • git pull origin <branch>
    • 回到主仓库:
      • git add <submodule-path>
      • git commit -m "Update submodule to latest commit"
    cd libfoo
    git pull origin main
    cd ..
    git add libfoo
    git commit -m "Update libfoo submodule to latest commit"
    
  7. 删除子模块

    • 从主仓库中删除子模块的引用,并从 .gitmodules 文件中移除。
    git submodule deinit <submodule-path>
    git rm <submodule-path>
    rm -rf .git/modules/<submodule-path>
    

示例

假设你有一个主项目,并且你想要将一个开源库作为子模块集成:

  1. 添加子模块

    git submodule add https://github.com/someuser/somelibrary.git lib/somelibrary
    

    这会将 somelibrary 仓库作为子模块添加到 lib/somelibrary 目录。

  2. 初始化和更新子模块

    git submodule update --init --recursive
    

    这会检出子模块的代码,并确保它处于主仓库指定的提交状态。

  3. 提交子模块更改

    git add lib/somelibrary
    git commit -m "Add somelibrary as a submodule"
    

总结

Git 子模块提供了一种有效的方式来管理项目中的外部依赖。通过将其他 Git 仓库嵌套在主仓库中,子模块可以帮助保持代码的组织性和模块化。尽管子模块增加了一些管理复杂性,但它们是处理共享和复用代码的一种强大工具。使用子模块 时,请确保定期更新和维护,以确保依赖项始终保持在所需的版本。

4.4 filter-branch 全局修改分支

filter-branch 可以全局修改分支的历史记录。

1) 开源前修改用户信息

do_commit_filter()
{       # '=' seems 完全相同,通配符*不起作用
  git filter-branch -f --commit-filter '
  if [ "${GIT_AUTHOR_NAME}" = denny ];
  then
    GIT_COMMITTER_NAME="Denny Wu";
    GIT_AUTHOR_NAME="Denny Wu";
    GIT_COMMITTER_EMAIL="wuqifu@gmail.com";
    GIT_AUTHOR_EMAIL="wuqifu@gmail.com";
    git commit-tree "$@";
  else
    git commit-tree "$@";
  fi' HEAD
}

do_env_filter()
{
  git filter-branch -f --env-filter '
   case "${GIT_AUTHOR_NAME} ${GIT_AUTHOR_EMAIL}" in
   *enny*)
   export GIT_AUTHOR_NAME="Denny Wu"
   export GIT_AUTHOR_EMAIL="wuqifu@gmail.com"
   ;;
   esac
   case "${GIT_COMMITTER_NAME} ${GIT_COMMITTER_EMAIL}" in
   *enny*)
   export GIT_COMMITTER_NAME="Denny Wu"
   export GIT_COMMITTER_EMAIL="wuqifu@gmail.com"
   ;;
   esac
   '
}

2)删除历史纪录中某个文件

# remove unnecessay file or directory, 如 passwords.txt
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD

4.5 小技巧

# git 通过 commit_id 找到开发分支。 
$ git branch -r –contains [commit_id] 

# git 通过代码 找到代码当前分支的 commit_id。
git log -S "代码关键字"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文