一、分支操作

分支是 Git 分布式版本控制系统中的重要特性。使用分支,可以在不影响主分支的情况下进行工作。

创建分支

1
$ git branch <branchname>

切换分支

当你切换分支的时候,Git 会重置你的工作目录,使其看起来像回到了你在那个分支上最后一次提交的样子。 Git 会自动添加、删除、修改文件以确保此时你的工作目录和这个分支最后一次提交时的样子一模一样。

1
2
$ git checkout <branchname>
$ git checkout -b <branchname> # 创建新分支,并立即切换到该分支下

查看分支

1
2
3
$ git branch # 查看所有分支
$ git branch --merged # 查看合并的分支
$ git branch --no-merged # 查看未合并的分支

删除分支

1
$ git branch -d <branchname>

合并分支

1
$ git merge <branchname> # 合并到当前分支

合并完之后,如果不再需要这个分支,就可以删除被合并的分支了。

还有一种合并分支的方式:变基

例如:使用 rebase 命令,将 experiment 分支变基到 master 分支

1
2
$ git checkout experiment
$ git rebase master

相对于 merge 来说,变基的方式使得历史提交更加整洁。

在实际开发中,我们就可以变基到 origin/master 上,然后再提交修改。这样就很方便维护,维护者直接 merge 合并即可。

注意!!!如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。

总的原则是,只对尚未推送或分享给别人的本地修改执行变基操作清理历史, 从不对已推送至别处的提交执行变基操作,这样,你才能享受到两种方式带来的便利。

二、标签和别名

标签

我们可以给某次提交打上标签,以示重要,比较常见的使用是用来标记发布结点(v1.0、v2.0 等)。

查看标签

1
2
$ git tag [-l 或 --list] # 标签列表
$ git show <tagname> # 查看某个标签的信息

创建标签

Git 支持两种标签:轻量标签(lightweight)与附注标签(annotated)。

  • 轻量标签:用于临时,或不想保存一些信息时使用的标签。

    1
    $ git tag <tagname>
  • 附注标签:附注标签是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间, 此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名并验证。

    1
    $ git tag -a <tagname> -m "decription"

后期打标签

如果忘记打标签了,可以在提交后补上标签。需要在命令末尾指定提交的校验和。

例如:

1
$ git tag -a v1.2 9fceb02

远程仓库打标签

默认情况下,git push 命令不会把标签推送到远程仓库上。创建完标签后,必须显式地推送标签:

1
$ git push origin <tagname>

删除标签

1
2
$ git tag -d <tagname> # 本地
$ git push origin --delete <tagname> # 远程

检出标签

如果你想查看某个标签所指向的文件版本,可以使用 git checkout 命令:

1
$ git checkout <tagname>

这会使你的仓库处于“分离头指针(detached HEAD)”的状态。如果你做了某些更改然后提交它们,标签不会发生变化, 但你的新提交将不属于任何分支,并且将无法访问,除非通过确切的提交哈希才能访问。 因此,如果你需要进行更改,比如你要修复旧版本中的错误,那么通常需要创建一个新分支:

1
$ git checkout -b <branch> <tagname>

如果在这之后又进行了一次提交,新的分支就会因为这个改动向前移动, 此时它就会和标签稍微有些不同,这时就要当心了。

别名

设置别名,可以更方便的使用命令。

例如:

1
2
3
4
$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status

使用 git commit 时,只输入 git ci 就可以了。

三、GitHub 项目贡献

项目贡献

很多情况下,我们都是没有权限直接更新他人的项目的分支的。这时需要了解 Fork 和 PR(Pull Reqeust)。

  1. 在 GitHub 原始项目中 派生(Fork),可以创建一个自己可写的项目派生仓库(可以在我们的 GitHub 仓库中找到)。
  2. 派生完后克隆到本地
  3. 创建分支,修改代码
  4. 推送到派生库

这样就可以将工作推送到派生仓库中,但是想要推送到他人的项目上,需要一个 拉取请求(Pull Request)

我们可以从 GitHub 上提交 PR 或使用 git request-pull 命令然后将随后的输出通过电子邮件手动发送给项目维护者。

冲突解决

假设项目维护者已经拉取了一串其他补丁,然后尝试拉取你的第一个分支,但是没有干净地合并。 在这种情况下,可以尝试变基那个分支到 origin/master 的顶部,为维护者解决冲突,然后重新提交你的改动:

1
2
3
$ git checkout <branchname>
$ git rebase origin/master # 变基到 origin/master 的顶部
$ git push -f <forkname> <branchname> # 强制推送

四、交互式暂存

在修改了大量文件后,希望这些改动能拆分为若干提交而不是混杂在一起成为一个提交时,交互式命令行非常好用。

我们可以使用 -i 参数:

1
$ git add -i

命令行会变成交互式,我们根据需要操作即可

五、贮藏和清理

贮藏

当我们在一个分支上进行了许多修改,这时我们想要切换到另一个分支上工作,但并不想提交,就需要用到 git stash 命令。

我们之前分支上的修改会被存储在栈上。

1
2
3
4
5
6
7
8
9
$ git stash
$ git stash push

$ git stash list # 查看贮藏的东西

$ git stash apply [stashname] # 应用指定的贮藏,不指定则默认指定最近的

$ git stash drop <stashname> # 移除指定的贮藏
$ git stash pop # 应用贮藏然后立即从栈上扔掉它

清理

使用 git clean 命令可以从工作目录中移除未被追踪的文件。

如果你改变主意了,你也不一定能找回来那些文件的内容。 一个更安全的选项是运行 git stash --all 来移除每一样东西并存放在栈中。