Git学习笔记 #4 GitHub合作开发

本文最后更新于:2024年4月20日 上午

接上文,本文介绍了 Git 基于 GitHub 的使用,以及合作开发的注意事项。文章的最后还留下了一些待填的坑...

本文大部分内容参考了 RCY 同学的教程,部分参考了 廖雪峰教程-Git菜鸟教程-Git,以及 Git 官网文档 Git-Documentation

GitHub 合作开发

以下内容也适用于不同的服务器平台,如 Gitee、GitLab 等。

新建远程仓库

从 GitHub 上创建一个空仓库后,通常有三个选择:

  • 直接克隆到本地,会生成一个仓库文件夹,里面只有一个 .git 文件夹。可以在仓库文件夹中创作。
  • 本地新建一个同名文件夹,再创建本地仓库,添加远程仓库,推送并绑定上游分支。
  • 本地已有的一个仓库(确保同名),添加远程仓库,推送并绑定上游分支。

对于第一种方法,只需要 git clone 命令即可,对于第二种方法,GitHub 提供了一系列指引命令:

1
2
3
4
5
6
7
$ echo "# test" >> README.md
$ git init
$ git add README.md
$ git commit -m "first commit"
$ git branch -M main # 重命名本地主分支,避免冲突,新版本特性
$ git remote add origin https://github.com/hewei2001/test.git
$ git push -u origin main # 推送并绑定上游分支

对于第三种情况,只需完成后面三步即可。

.gitignore

在通过 GitHub 新建仓库时,我们会发现有个 Add .gitignore 按钮,这有什么用呢?实际上我们知道,维护真正项目时可能有一次修改会涉及到多个文件,这个时候一般大家会倾向于使用 git add . 的简单操作。

但是,并非所有文件都应该被放入 Git 仓库中,如:

  • IDE / 编辑器 的配置文件(如 .vscode、.idea 等);
  • 数据库文件;
  • 带有敏感信息的文件。

这和便利的命令形成了矛盾,为此出现了特殊文件 .gitignore,它可以决定哪些的文件不需要添加到版本管理中。一个样例如下:

1
2
3
4
5
6
7
8
9
10
11
12
# Python3 的缓存文件(预编译模块)
__pycache__
# Vscode 的配置文件
.vscode
# Pycharm 等Jet的配置文件
.idea
# 忽略项目中所有 ckpt 目录
ckpt/
# 忽略项目根目录下的 data 目录
/data/
# 忽略项目根目录下的 foo 目录下所有的 model.pt
/foo/**/model.pt

以行为单位,一行写一个规则,决定什么不被添加,书写规则也很简单:

  • # 开头的一行是注释,用 \ 进行转义。
  • 若规则不包含 /,会对 .gitignore 同路径下的文件和目录进行屏蔽;
  • 若规则以 / 结束,则会匹配项目中所有同名目录下的内容,但不匹配同名文件;
  • 若规则以 / 开始,则会从项目根目录开始匹配;
  • * 匹配除了 / 以外的任意字符串,** 匹配完整路径名;
  • ? 匹配除了 / 以外的任意单个字符;
  • 区间表示,如 [a-zA-Z],可以用于匹配任何一个区间范围内的字符;
  • ! 开头的模式标识否定,该文件将会再次被包含,通常用于在屏蔽的文件中添加特例
  • 不能识别中文,因为默认编码是 GBK。

创建一个 .gitignore 文件最便捷的方法是,在创建仓库时勾选 GitHub 自动创建,并在选项中选择合适的 .gitignore 文件模板,再克隆到本地手动补充。

在实际工程中,用 GitHub 创建仓库还可以便捷地添加合适的 LICENSE 文件。

远程服务器拒绝

如果你是在一个大合作团队中工作,很可能是 main 被锁定了(只有 Collaborators 有权限推送),其他人需要 Pull Request 流程来合并修改。

如果你直接提交到本地 main,然后试图推送修改,你将会收到这样类似的信息:

1
! [远程服务器拒绝] main -> main (TF402455: 不允许推送(push)这个分支; 你必须使用pull request来更新这个分支.)

这里推荐一个做法:Fork 最新的仓库,此时你将拥有这个远程仓库的从分支——你的用户名就是从分支名。再将你的修改提交到这条分支,最后通过 GitHub 网站来提交一个 PR,请求主分支拉取并合并你的从分支。

当然,如果只是几个人的小开发团队,还是建议在仓库的 Settings 界面找到 Collaborators,直接添加队友来得方便。

此外,即使是在小开发团队中,也可能会遇到 push 时远程服务器拒绝的情况,此时大概率是因为产生了分叉 (Branch Diverged) !具体的处理办法参见上一章。

upstream

在前文介绍 Push 时,曾提过上游(upstream)的概念,对于个人开发而言,upstream 只是标识了多个远程仓库或分支中的某个默认值。但在合作开发,特别是需要提 PR 时,upstream 有其特定意义。

  • upstream 通常指代你所 fork 的原始仓库,你无权修改。
  • origin 则是你所 fork 下来的仓库,你有权修改。

因此,当需要对一个大型项目贡献时,你的操作流程应该是:

  1. 先在 GitHub 上 fork 原始仓库,得到你所有的仓库。

  2. 再 clone 你所有的仓库到本地,此时它默认为 origin 分支。

  3. 将原始仓库添加到 upstream 以保持联系,跟进其变化:

    1
    2
    $ git remote add upstream git://github.com/<aUser>/<aRepo.git>
    $ git remote -v # 查看远程仓库情况

    当原始仓库有变化时,可以拉取其更新:

    1
    2
    $ git fetch upstream  # 如果设置了 upstream 可以缺省
    $ git merge
  4. 当本地做出提交时,先推送到自己的 origin

    1
    $ git push origin  # 如果不加 origin 会被远程服务器拒绝

    然后再通过 Pull Request 请求原始仓库拉取你的修改。

暂存本地修改

有时候在本地修改进行到一半的时候,需要拉取远程版本,此时如果直接 git pull 则会和本地版本产生冲突。一个解决办法是先将本地的代码 commit 再去 fetch 远程的并手动 merge。但是这样则会提交一个半成品的节点。

Git 提供了一个 git stash 命令来解决这个问题:将当前未提交的修改(包括工作区和暂存区的修改)先暂时储藏起来,这样工作区干净了后,就可以直接拉取线上更新。

1
2
3
4
5
6
# 暂存修改
$ git stash
# 拉取更新
$ git pull
# 弹出之前暂存的内容,之后可能需要手动 merge 冲突文件
$ git stash pop

如果需要多次暂存——「修改,暂存,再修改,再暂存」,则可以使用如下命令:

1
2
# 查看储藏记录列表
$ git stash list

多远程与多分支

实践中遇到的最多的问题:

  • 创建空分支:https://www.jianshu.com/p/a18487d987ac
  • 推送本地所有分支和拉取远程所有分支:https://blog.csdn.net/toopoo/article/details/85260277
  • 将一个项目同时从本地推送到 GitHub 和 Gitee:https://www.cnblogs.com/poloyy/p/12215199.html
  • 将 upstream 的分支拉到本地后没有对应的同名分支:

高端的 Git

高端的操作往往意味着危险的操作,以下将介绍前文未提及的一些操作,同时也挖下一些坑以后来填。

版本回退 (Reset)

有时候你可能希望放弃 Git 仓库中的一部分提交,退到其他某处,这种情况下可以:

1
2
$ git reset <Commit ID or Branch>         # 让 Git 仓库回退到某个记录或分支位置
$ git reset <Commit Id or Branch> --hard # 让所有区回退到某个记录或分支位置(将丢失你工作区和暂存区的数据)

这种情况下可以带着分支一起回退,然后重新 commit,走一条完全不同的道路,而放弃了部分数据。

但是,如果你 reset 完后又后悔了,该怎么办?没关系,只要你没玩 gc 这样的危险指令,那么你 Git 仓库中的数据总有机会找回来。

1
$ git reflog # 查看最近一些变动快照的操作与版本号

在看到后面的快照的版本号后,则可以 reset 回去。

Cherry-Pick

一个相对高端的分支管理命令,将一些提交复制到当前所在的位置(HEAD)下面,这些提交可以来自其他分支,但不一定是顺序的!

1
$ git cherry-pick <Commit ID>

获取帮助

无论是本博客,还是网上的文档,甚至官方的教程,都未必能把每个指令的每个参数、用法提到,因此 Git 自带的帮助文档就很重要:

1
2
3
$ git add --help
$ git help add
# 以上两个指令的效果等价,都会

Git学习笔记 #4 GitHub合作开发
https://hwcoder.top/Git-Note-4
作者
Wei He
发布于
2021年9月5日
许可协议