Git 使用教程, 使用 GitHub/Gitlab 进行团队合作

  2013-11-22 00:00:00 CST

  Jingwen Peng

  Git

Git

注:写给开源社区 2013级 的成员们。

本篇文章分两个部分。

Git 是一个版本控制工具,是 Linux 内核开发者 Linus Torvalds 为了更好地管理 Linux 内核开发而创立的。 版本控制 (Revision Control) 是维护工程蓝图的标准方法,能追踪工程从诞生一直到定案的过程。此外,版本控制也是一种软件工程技巧,藉此能在软件开发的过程中,确保由不同人所编辑的同一档案都得到同步。常见的版本控制工具有 git,svn,perforce,mercurial (hg) 等等。

Git 是一个遵循 GUN v2 的开源软件,从诞生至今,已经为相当多的开源项目所采用。GitHub 这个提供代码托管的服务网站近年来也相当火爆,最近又推出了 GitHub Pages,又吸引了很多的 Blog 转移到 GitHub,又进一步增加了其用户数量。

Linus Torvalds 自嘲地取了这个名字 “git”。在英式英语中指一个愚笨或者不开心的人。

I’m an egotistical bastard, and I name all my projects after myself. First Linux, now git.

仅从命名由来就能看出,git 的目的就是为了简单高效的管理代码。


Git 使用教程

优势

在使用 Git 之前,要弄明白为什么要用 Git,看一看 Git 有怎么样的优势。

  • 速度很快
  • 支持离线操作
  • 强大的分支功能
  • 保持工作独立
  • 选择代码提交
  • 回滚操作
  • 不依赖中央仓库
  • 仓库目录结构简洁
  • 有 GitHub、Gitlab 之类的社交平台

PS:我的博客就放在 GitHub,当你发现有某个错别字,可以直接帮我修正错误然后给我发 Pull Request,我看到之后进行 Merge。错误就修正了。或者你想对我的文章有所补充或修改,也可以直接编辑然后向我发送请求。


安装

Linux

1
2
3
4
5
6
7
8
9
10
# 1.源码安装
# 下载 git 源码包
tar -xvf git*.tar.gz
cd git*
./configure --prefix=/usr/local/
make
make install
# 2.软件包管理器
yum install git-core #redhat
apt-get install git-core #ubuntu

Mac OS X

不推荐使用源码安装,建议使用 brew 或者 macports 这类的包管理器,个人更推荐使用 brew。 以 brew 为例。

1
2
3
4
5
6
# 安装 brew。若已安装,跳过。
ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go/install)"
# 更新 brew
brew update
# 安装 git
brew install git

Windows (不建议使用) Git 最早是 Linux 平台的工具,随着用户量的增大和使用范围的延伸,也出现了 Windows 平台的 Git。但 Windows 上的 Git 不支持中文,也有许多功能上的 Bug,不建议使用。Git,还是在 Linux/Unix 上用的爽。如果你不得不工作在 Windows 上,可以使用 msysgit。http://msysgit.github.com/


配置

首次使用 Git 的时候需要进行一些配置。

配置文件分为三个层次:

  • 系统全局配置,影响到系统上的所有用户。位于 /etc/gitconfig
  • 用户配置,影响到单个用户。位于 ~/.gitconfig
  • 仓库配置,影响到当前的仓库。位于 .git/config

以上上层次优先级依次升高。

配置的时候即可以直接用编辑器打开文件直接修改,也可以使用 git config 命令进行修改。

  • 修改全局配置 git config --system
  • 修改用户配置 git config --global
  • 修改仓库配置 git config
  • 查看当前配置 git config --list

OK,了解了如何修改配置后,开始配置的你的 Git。一般使用 --global 进行配置,这样修改用户级别的配置文件,否则你要在每个仓库都要设置一遍。

首先设置你的用户名和邮箱,使你提交版本的时候让其他人知道你的信息。 git config --global user.name "Peng Jingwen" git config --global user.email "pengsrc@icloud.com"

接下来你也可以指定你的编辑器和文件对比工具。 git config --global core.editor "vim" git config --global merge.tool "vimdiff"

下面指定你的 Push 方式,可选择 matching、simple、current、upstream、nothing。这里我使用 simple。 nothing:什么都不 Push matching:Push 所有名字相匹配的分支 upstream:Push 给上游 simple:Push 给上游,名字不匹配则不 Push,最安全的方式,Git 2.0 会将其作为默认值。 current:Push 当前分支到名字匹配分支 git config --global push.default simple

Git 的配置文件 gitconfig 大概是这个样子的

1
2
3
4
5
6
7
8
9
[user]
        name = Peng Jingwen
        email = user@mail.example.com
[core]
        editor = vim
[merge]
        tool = vimdiff
[Push]
        default = simple

Git 配置好之后就可以在本地创建仓库或者从 Git 服务器上获取仓库。Git 支持四种协议,ssh、git、http、https。我平时用到最多的为 ssh 协议。 下面随便 clone 一个仓库来检查一下 Git 是否工作正常。 git clone git@github.com:example/test.git

git 通常是通过 ssh 进行认证的,将 ssh 的公钥提交给 git 服务提供方,可以直接通过密钥登录,进行文件传输。 检查 ~/.ssh 目录下是否已经有 rsa 密钥,如果有则跳过生成。 生成密钥,ssh-keygen 获取生成的公钥,cat ~/.ssh/id_rsa.pub 之后将密钥添加到在 GitHub/Gitlab 注册的账号中。


使用

新建并初始化仓库,或者从现有的仓库 clone 一个 mkdir test cd test git init

开始工作,这时 Git 还没有对你的文件进行跟踪。 Git 跟踪的文件分三种状态:

  • Modified (working directory):被修改过的文件
  • Staged (staging directory):暂存区文件
  • Committed (git directory):仓库中的文件

下面附上 git file lifecycle 图一张。

Git-Life-Cycle

Git 暂存区有的这个概念使的版本控制变得很方便,暂存区的文件就是下一个版本的文件变化清单,你可以很方便的控制文件,可以避免一些不必要的文件被加入,比如 Mac OS X 的 .DS_Store 或者一些编译后的文件。

这里顺便提一下 .gitignore,该文件在仓库的根目录下,记录了一些需要排除掉的文件。比如一些编译以后的文件、一些 IDE 与本机相关的配置文件或者操作系统本身在目录留下的文件如 .DS_Store。 下面这个文件是 Android 开发时常用到的 .gitignore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# built application files
*.apk
*.ap_

# files for the dex VM
*.dex

# Java class files
*.class

# generated files
bin/
gen/

# Ignore gradle files
.gradle/
build/

# Local configuration file (sdk path, etc)
local.properties

关于 .gitignore 的排除内容可以参考 GitHub 的 gitignore https://github.com/github/gitignore

添加文件到暂存区: 说了这么多,回到刚才的工作上来。在任何时候使用 git status 来查看当前的 Git 状态。当有新文件的时候,查看 Git 状态,会提示 Untracked Files,这是使用 git add [filename] 来添加文件,进行跟踪。git add . 可以将所有未跟踪文件都加入暂存区。这时再去查看状态,会提示 changes to be committed,这就是暂存区中待提交到下一个版本的文件列表。

增加新版本: 当你觉得工作的差不多的时候,是时候创建一个新版本了。使用 git commit,这时会跳出刚才配置中指定的文本编辑器,阅读里面的注释文字可以得知,这个是让你写版本备注的。写完备注保存退出,一个新版本就提交完成了,当然也可以不保存退出,这样撤销了版本提交。同样也有更快的提交方法,git commit -m "This Is Commit Message" 这样可以直接添加版本备注并提交。git commit -s 这样会自动为你增加签名,就像这样 Signed-off-by: Peng Jingwen <pengsrc@icloud.com>

查看回滚历史版本: 在工作过程中,发现这个版本简直太糟糕了,混乱不堪,那就赶紧回滚到上一个版本吧。git log 会列出所有的版本,找到之前比较满意的版本复制 commit 后面的 hash 值,git reset --hard [hash] 这样就直接回到了你满意的那个版本。git reset 用法还有很多,可以自行查阅文档。

推送变更: 代码放在本地安全性得不到充足的保障,把它传到 Git 服务器上去会使你代码更安全,即使本的计算机出现故障,找一台新机子,git clone 一下,就又可以毫无压力的继续工作了。如果你有多台计算机,将代码推送的服务器上去也能方便的实现多台设备的代码同步工作。想把代码开源或者是想进行团队合作,使用 Git 和 Git 服务器也是相当的方便。

如果是本地建立的仓库,默认没有 Git 服务器地址,如果是 clone 过来的仓库,服务器地址会出现在你的仓库中。使用 git remote -v 来查看服务器端。如果没有服务器地址,这时候在 GitHub 或 Gitlab 上新建项目,将得到的服务器地添加到你的本地仓库。使用 git remote add [name] [url] 添加远程仓库地址。之后使用 git push [name] master 来推送的你仓库。 常用操作 git clone git fetch git pull git push git merge

分支管理: 在工作中,可能想增加一个测试性的功能,或者你不想影响现有的工作进行一些测试。这时,就可以使用分支。创建一个新分支,在分支中工作。如果觉得新特性还不错那么就回到主分支,将分支合并过来,后删除分支;如果觉得新想法不怎么好,那么删掉分支就 OK 了,对主分支没有任何影响。

常用操作:

1
2
3
4
5
6
7
8
git branch test # 创建 test 分支
git checkout test # 转到 test 分支
git checkout master # 转到 master 分支
git merge # 合并 test 分支
git checkout test # 转到 test 分支
git checkout master # 转到 master 分支
git branch -v # 列出全部分支和 commit 版本
git branch -d test # 删除 test 分支

git merge 是把两个版本融合在一起,然后建立新的 commit,如果两个分支的在同一文件的同一个地方都作了修改,那么就会发生冲突,需要手动解决冲突后才能融合。

上面就是 Git 的一些常用操作,当然 Git 的操作还有很多很多,这里也不能一一列举,有用到别的操作,可以自行查阅文档。

一些Git的使用文档: Git - The Simple Guide A Visual Git Reference Git shouldn’t be so hard to learn Pro Git professional version control Git Magic Got GitHub


使用 GitHub/Gitlab 进行团队合作

读完上面的 Git 使用教程,应该知道 Git 是个什么东西了,掌握了一些使用方法。Git 除了用于代码管理、版本控制之外。最最重要的用途要数团队合作了。想象一下如果没有分布式的版本控制,那么团队合作将成为一场噩梦,代码不同步,手动合并代码工作量巨大,等等。

GitHub 是一个用于使用 Git 版本控制系统项目的共享虚拟主机服务,同时提供付费账户和为开源项目提供的免费账户。它由 GitHub 公司的开发者 Chris Wanstrath、PJ Hyett 和 Tom Preston-Werner 使用 Ruby on Rails 编写而成。 如今 GitHub 已成为最流行的开源代码托管平台,超越了 Sourceforge、Google Code 和微软的 CodePlex。现在的 GitHub 不仅仅是一个代码托管工具,有人拿它写书,有人用它写博客,有人用它创作音乐,甚至还有人拿它发婚礼请柬。GitHub 已经成为的一切开放源码软件的基石。开发人员喜欢它,基于它进行协作,并不断通过它开发令人惊叹的项目。除了​​代码托管,GitHub 的主要吸引力是使用它作为一个协作开发工具,特别是使团队工作更有效率,更高生产力。

还有不得不说的就是 GitLab,是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的 Git 项目仓库,可通过 Web 界面进行访问公开的或者私人项目。说白了就是对 GitHub 的赤果果山寨,但它是开源的,其本身就托管在 GitHub 上,适合于组织团体搭建自己的 Git 服务器。Gitlab 的很多操作和 GitHub 几乎是一致的。使用 GitHub 进行团队合作,也同样适用于使用 Gitlab 进行团队合作,关于 Gitlab 的部分不再细说。

下面的介绍有部分翻译自 Team Collaboration With GitHub


增加团队成员

有两种常用的方法在 GitHub 上建立团队合作:

  • 组织 - 组织的所有者可以针对不同的代码仓库建立不同访问权限的团队。
  • 团队 - 代码仓库的所有者可以为单个仓库增加具备只读或者读写权限的协作者。

组织 如果您管理几个团队,想为每个团队设置不同的权限级别,或者为不同的代码仓库增加不同的成员。组织 (Organizations) 将是最好的选择。任何 GitHub 用户帐户已经可以创建免费的开源代码库的组织。要创建一个组织,只需浏览组织设置页面

Create-Organization

要访问组织的团队页面,你可以简单地去页面 http://github.com/organizations/[组织名称]/teams 来查看,或者访问页面 https://github.com/organizations/[组织名称]/teams/new 来创建新的具备 3 种不同的权限级别的团队成员。

Organization-Permission

团队 团队成员主要用于读写访问个人账号所拥有的代码仓库。你可以通过 https://github.com/[用户名]/[代码仓库名称]/settings/collaboration 来增加合作者 (其他 GitHub 个人账号)。

Add-Team-Member

这样,每团队成员将会看到代码库页面的访问状态的变化。在拥有对代码库的写访问权限后,我们可以做一个 git 克隆,进行代码变更,用 git 拉取和归并远程存储库中的任何变化,并最终将本地的变化 git 推送到远程代码库:

Repo-Access

在 Gitlab 中同样可以增加组织,只不过 Gitlab 中称作组。

Gitlab-Group

在 Gitlab 中向某个团队增加成员可以到该项目的设置 -> 团队 -> 新成员,同样也可以设置每位成员的访问权限。

Gitlab-Group-Permission


Pull 请求

Pull 请求是一个非常棒的方式,通过 Fork 一个新的代码库用来独立开发,并将变更贡献回原始代码库。在一天结束的时候,如果我们愿意,我们可以发送一个 Pull 请求给代码库所有者,来合并我们的代码更改。Pull 请求本身可以引起合作者之间的评论,包括代码质量,功能,甚至总体战略等。

发起一个 Pull 请求

GitHub 有两种 Pull 请求方式: Fork & Pull 方式 – 用于在公共库中,我们没有推送 (Push) 权限。 共享库方式 – 用于私有代码仓库,我们有推送 (Push) 权限。这种情况下没有必要进行 Fork。

下面的工作流程是在两个用户 (原始代码库拥有者,和 Fork 代码库拥有者) 之间的 Fork & Pull 方式:

  1. 进入你想贡献修改的 GitHub 代码库,点击 “Fork” 按​​钮来创建自己的 GitHub 帐户上的代码库克隆: Fork

  2. 这将在自己的帐户上创建一个该代码库的复制: Forked

  3. clone 一份代码库到本地计算机 git clone [ssh-url] [folder-name] cd [folder-name]

  4. 一般情况下,每一个新的功能,我们将创建一个新的 Git 分支。这是一个很好的做法,因为在未来,如果经过一番讨论后我们需要进一步更新分支,Pull 请求将被自动更新。让我们创建一个新的分支做一个非常简单的变化修改的 readme.md。 git checkout -b [new-feature]

  5. 在为这个新功能增加文件后,我们只需要将修改提交到这个新分支上,然后切换回 master 分支。 git add . git commit -m "Information Added in Readme" git checkout master

  6. 在这里,我们需要将新分支推送到远程代码仓库里。首先,我们需要检查这个新功能的分支名称以及其在远程仓库的别名,然后我们用 git push [git-remote-alias] [branch-name] 推送这个变更。

  7. 进入我们 Fork 的代码库的 GitHub 页面,选择为这个新功能建立的分支,然后点击 Pull Request 按钮。 Pull-Request

  8. 提交 Pull 请求后,页面将直接跳转到原始库的 Pull 请求页面,我们将看到我们提交的 Pull 请求,作为一个新的 Issues,以及作为一个新的 Pull 请求。 Pull-Requested

  9. 在经过讨论后,Fork 的代码库的作者可能想为这个新功能增加一些新的改动。在这种场景下,我们需要在本地计算机上 Checkout 这个同样的分支,修改,提交,并推送回 GitHub。当我们再次访问原代码库的 Pull 请求页面的时候,会发现上次提交的 Pull 请求已经自动更新了。 Pull-Update

合并一个 Pull 请求

  1. 直接在 GitHub 上合并:如果我们想直接在 GitHub 上进行合并,必须确保没有冲突。原始库的所有者可以通过简单地点击 Merge Pull Request 按钮来进行合并。 Merge

  2. 在本地计算机上进行合并:另外一种情况,合并的时候可能会遇到冲突,点击上部的 Info 图标,GitHub 有非常清晰的指导,怎么从贡献者的分支上下拉代码变更到本地,合并并解决冲突。 Conflict

在软件开发团队中有很多不同的代码分支模型。这里有两种非常常用的工作流程模型:

  1. 简单分支模型以及 Pull 请求
  2. 更加广泛的分支模型

至于采用何种分支模型,取决于团队,项目,以及当时的状态。

同样在 Gitlab 上也可以进行 Pull Request 和 Merge Request。 Gitlab-Pull-Merge


错误跟踪

在 GitHub 中,缺陷跟踪的中心是问题列表 (Issues)。虽然问题列表主要是为了跟踪缺陷,但我们经常会用以下面的方式。

  • 缺陷:需要进行修正的地方。
  • 功能:需要实现的很酷很棒的新点子。
  • 待完成清单:待完成的检查清单。
  1. 标签:具有不同颜色的类别,用来帮助过滤问题。

  2. 里程碑:附加在每一个问题上的日期分类,可用于确定哪些问题需要在下一个版本解决。 此外,由于每个问题都定有里程碑,每当一个问题解决,它会自动更新进度条。

  3. 搜索:搜索时能自动列出匹配的问题列表和里程碑。 Search

  4. 分配:每个问题都能分配一个人负责进行解决,同时这也能让我们知道目前我们需要工作在什么上面。 Issue

  5. 自动关闭:包含 Fixes/Fixed/Close/Closes/Closed #问题编号 的提交记录,将自动关闭该问题。 Issue-Close

  6. 提及或者引用:任何人在评论的时候在消息文本中包含 #[问题编号],将自动生成该问题的链接,使得在讨论的过程中能非常容易地提及相关的问题。 Issue-Auto-Close

Gitlab 的 Issues 功能和 GitHub 大致相同。 Gitlab-Issue


分析

有两个工具-图形和网络,让我们能洞察存储库的变化。GitHub 图 提供了代码库的合作者,以及代码提交的直观展现,而 GitHub 网络 可视化直观地展现了每一个贡献者和他们在所有分支上的代码提交。这些分析和图形非常强大,尤其是当在团队中工作。

图 (Graphs) 图提供了详细的分析,包括:

  • 贡献者:有哪些代码提交者?他们增加或者删除了多少代码行?
  • 代码提交活动:在过去的一年中,这些代码提交主要发生在哪些周?
  • 代码频率:在整个项目的生命周期的不同阶段,提交了多少代码行?
  • 记录卡:代码提交通常发生在每一天的什么时候?

Graph

网络 (Network) GitHub 网络 (Network) 是一个非常强大的工具,让我们能看到每一个贡献者的代码提交,以及这些提交与其他的提交有什么关联。当我们作为一个整体观看这个网络的可视化展现时,我们能看到每一个库,每一个分支,和每一个提交。 Network

Gitlab 上类似的网络功能。 Gitlab-Network


代码审计

对于每个提交 (commit),GitHub 有个干净的接口用来进行评论,甚至是对某行代码进行评论。在进行逐行代码评审的时候,针对单行代码提出评论和问题的功能就显得非常重要了。打开提交 (commit) 界面的顶部的检查框,就能显示行内评论。 Commit

  1. 对比 branch/tags/SHA1:使用 URL 模式。 https://github.com/[username]/[repo-name]/compare/[starting-SHA1]...[ending-SHA1] 可以用分支或者标签名代替 SHA1 Compare

  2. 去除空格进行对比:增加 ?w=1 到对比的URL尾部。 Compare-Whitespace

  3. Diff:增加 .diff 到 URL 的后面能得到 git diff 输出的纯文本信息。在写脚本的时候,这个功能非常有用。

  4. Patch:增加 .patch 到 URL 的后面能得到电子邮件补丁提交格式的 git diff 输出的信息。

  5. 行链接:在查看文件时,点击任何行号,GitHub 将会在URL后面增加一个 #行号 ,并且将该行的背景颜色置成黄色。这能干净利落地标识代码文件的某一行。我们同样能通过增加 #开始行号-结束行号 来指定一个范围。


文档

在这段,我们将探讨两种文档方法:

  1. 正式文档:使用 GitHub Wiki 生成正式的项目文档。
  2. 非正式文档:使用 GitHub Hubot 来归档团队内部的讨论,以及与 Hubot 互动而自动获得的非常有趣的信息。
  3. 提及,快捷键和表情符号

GitHub 维基 (Wiki) 每个 GitHub 代码库都可以生成一个维基,这样非常方便地将代码和文档存放在同一个存储库中。要创建维基,访问主标题的维基选项卡,并设置创建页面的信息。其实维基也有自己的版本,并可以将数据复制到本地机器进行更新,甚至是离线访问。 Wiki

有一件事我觉得非常有用的是可以将 GitHub 的维基整合到源代码中,这样我就不必维护两个独立的 Git 项目了。要做到这一点,我将 Wiki 作为 git 子模块 增加到主分支上。 git submodule add git@github.com:[username]/[repo-name].wiki.git git add . git commit -m "added wiki as submodule" git Push origin master

现在,维基就作为一个子模块显示在代码库项目中。 Wikied

Gitlab 的 Wiki 功能。 Gitlab-Wiki


以上就是 Git 使用教程和 GitHub/Gitlab 团队合作教程,如有疑问或者错误请联系我,或者直接给我发 Pull Request 吧。

如果您有疑问或建议,请在下方评论区域留言

遵循 BY-NC-ND 协议

评论功能加载中...