Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 103 – 收集有关 Git 的信息

作者:
Oleg Broytman <phd at phdru.name>
状态:
已撤回
类型:
信息性
创建日期:
2015 年 6 月 1 日
发布历史:
2015 年 9 月 12 日

目录

重要

本 PEP 已撤回。

×

它过于通用,并没有真正涉及 Python 开发。它不再更新。

内容已移至 Python Wiki。请在 wiki 中进行后续更新。

摘要

本信息性 PEP 收集有关 Git 的信息。当然,Git 有很多文档,因此本 PEP 重点关注更复杂(且与 Python 开发更相关)的问题、场景和示例。

计划未来扩展本 PEP,收集 Mercurial 和 Git 场景的等效信息,以帮助将 Python 开发从 Mercurial 迁移到 Git。

PEP 作者目前不打算撰写关于将 Python 开发从 Mercurial 迁移到 Git 的流程 PEP。

文档

Git 附带了大量在线和离线文档。

新手文档

Git 教程:第 1 部分, 第 2 部分

Git 用户手册日常 Git 与 20 条命令左右Git 工作流

高级文档

Git Magic,有多种语言翻译。

Pro Git。关于 Git 的书。在 Amazon 购买或下载 PDF、mobi 或 ePub 格式。它有许多不同语言的翻译。从 GArik 下载俄语翻译。

Git Wiki.

Git Buch(德语)。

离线文档

Git 内置帮助:运行 git help $TOPIC。例如,运行 git help gitgit help help

快速开始

下载和安装

Unix 用户:使用您的包管理器下载并安装

Microsoft Windows:下载 git-for-windows

MacOS X:使用 XCode 安装的 Git,或从 MacPortsgit-osx-installer 下载,或使用 Homebrew 安装 Git:brew install git

git-cola仓库)是一个用 Python 编写并采用 GPL 许可的 Git GUI。支持 Linux、Windows、MacOS X。

TortoiseGit 是一个基于 TortoiseSVN 的 Windows Shell Git 界面;开源。

初始配置

这段简单的代码经常出现在文档中,但它很重要,所以在这里重复一下。Git 在每次提交中存储作者和提交者的姓名/电子邮件,因此请配置您的真实姓名和首选电子邮件

$ git config --global user.name "User Name"
$ git config --global user.email user.name@example.org

本 PEP 中的示例

本 PEP 中的 Git 命令示例采用以下方法。假设您(用户)正在使用名为 python 的本地仓库,该仓库有一个名为 origin 的上游远程仓库。您的本地仓库有两个分支 v1master。对于大多数示例,当前检出的分支是 master。也就是说,假设您已经做了类似的操作

$ git clone https://git.python.org/python.git
$ cd python
$ git branch v1 origin/v1

第一个命令将远程仓库克隆到本地目录 python 中,创建一个新的本地分支 master,将其上游远程跟踪分支设置为 remotes/origin/master,并将其检出到工作目录中。

最后一个命令创建一个新的本地分支 v1 并将其上游远程跟踪分支设置为 remotes/origin/v1。

可以使用以下命令达到相同的结果

$ git clone -b v1 https://git.python.org/python.git
$ cd python
$ git checkout --track origin/master

最后一个命令创建一个新的本地分支 master,将其上游远程跟踪分支设置为 remotes/origin/master,并将其检出到工作目录中。

分支

Git 术语可能有点误导。例如,“分支”这个术语。在 Git 中它有两个含义。分支是提交的定向行(可能包含合并)。分支是分配给提交行的标签或指针。区分何时谈论提交以及何时谈论它们的标签很重要。提交行本身是未命名的,通常只会延长和合并。另一方面,标签可以自由创建、移动、重命名和删除。

远程仓库和远程分支

远程跟踪分支是您本地仓库中的分支(指向提交的指针)。它们存在是为了让 Git(和您)记住从哪个远程仓库拉取了哪些分支和提交,以及推送到哪个远程仓库(您可以从许多远程仓库拉取和推送到许多远程仓库)。远程跟踪分支位于 remotes/$REMOTE 命名空间下,例如 remotes/origin/master

要查看远程跟踪分支的状态,请运行

$ git branch -rv

要查看指向提交的本地和远程跟踪分支(和标签)

$ git log --decorate

您永远不会在远程跟踪分支上进行自己的开发。您创建一个具有远程分支作为上游的本地分支,并在该本地分支上进行开发。在推送时,Git 将提交推送到远程仓库并更新远程跟踪分支;在拉取时,Git 从远程仓库获取提交,更新远程跟踪分支并快进、合并或变基本地分支。

当你进行第一次克隆时,像这样

$ git clone -b v1 https://git.python.org/python.git

git 将远程仓库 https://git.python.org/python.git 克隆到目录 python,创建一个名为 origin 的远程,创建远程跟踪分支,创建一个本地分支 v1,将其配置为跟踪上游 remotes/origin/v1 分支,并将 v1 检出到工作目录中。

一些命令,例如 git status --branchgit branch --verbose,会报告本地分支和远程分支之间的差异。请记住,它们只与您本地仓库中的远程跟踪分支进行比较,并且这些远程跟踪分支的状态可能已过时。要更新远程跟踪分支,您要么从远程仓库 fetch 并合并(或 rebase)提交,要么在不更新本地分支的情况下更新远程跟踪分支。

更新本地分支和远程跟踪分支

要在不更新本地分支的情况下更新远程跟踪分支,请运行 git remote update [$REMOTE...]。例如

$ git remote update
$ git remote update origin

Fetch 和 Pull

两者之间存在重大差异

$ git fetch $REMOTE $BRANCH

$ git fetch $REMOTE $BRANCH:$BRANCH

第一个命令从 $REMOTE 仓库中名为 $BRANCH 的分支获取您仓库中不存在的提交,更新远程跟踪分支,并将头提交的 ID(哈希值)留在文件 .git/FETCH_HEAD 中。

第二个命令从 $REMOTE 仓库中名为 $BRANCH 的分支获取您仓库中不存在的提交,并更新本地分支 $BRANCH 及其上游远程跟踪分支。但它在非快进的情况下拒绝更新分支。并且它拒绝更新当前分支(当前检出的分支,即 HEAD 指向的分支)。

第一个命令由 git pull 在内部使用。

$ git pull $REMOTE $BRANCH

等价于

$ git fetch $REMOTE $BRANCH
$ git merge FETCH_HEAD

当然,在这种情况下,$BRANCH 应该是您的当前分支。如果您想将不同的分支合并到当前分支,请首先更新该非当前分支,然后合并

$ git fetch origin v1:v1  # Update v1
$ git pull --rebase origin master  # Update the current branch master
                                   # using rebase instead of merge
$ git merge v1

但是,如果您尚未推送 v1 上的提交,那么场景会变得有点复杂。Git 拒绝更新不可快进的分支,并且您不想强制拉取,因为那会删除您未推送的提交,您需要恢复。所以您想对 v1 进行变基,但您不能对非当前分支进行变基。因此,在合并之前检出 v1 并对其进行变基

$ git checkout v1
$ git pull --rebase origin v1
$ git checkout master
$ git pull --rebase origin master
$ git merge v1

可以将 git 配置为一次性获取/拉取几个分支或所有分支,这样您就可以简单地运行

$ git pull origin

甚至

$ git pull

获取/拉取的默认远程仓库是 origin。默认的引用集使用匹配算法计算:git 获取两端具有相同名称的所有分支。

Push

推送相对简单。只有一个命令 push。当你运行

$ git push origin v1 master

git 将本地 v1 推送到远程 v1,将本地 master 推送到远程 master。与此相同

$ git push origin v1:v1 master:master

Git 将提交推送到远程仓库并更新远程跟踪分支。Git 拒绝推送非快进提交。无论如何,您可以强制推送,但请记住——您可以强制推送到您自己的仓库,但不要强制推送到公共或共享仓库。如果您发现 Git 拒绝推送非快进提交,最好从远程仓库 fetch 并合并提交(或在 fetch 的提交之上 rebase 您的提交),然后推送。只有当您知道自己在做什么以及为什么这样做时才强制推送。请参阅下面的提交编辑和注意事项部分。

可以将 Git 配置为一次性推送几个分支或所有分支,这样您就可以简单地运行

$ git push origin

甚至

$ git push

默认的推送远程仓库是 origin。Git 2.0 之前的默认推送引用集使用匹配算法计算:Git 推送两端具有相同名称的所有分支。Git 2.0+ 中的默认推送引用集使用简单算法计算:Git 将当前分支推回其 @{upstream}。

要在 Git 2.0 之前配置为新行为,请运行

$ git config push.default simple

要在 Git 2.0+ 中配置为旧行为,请运行

$ git config push.default matching

如果分支是远程非裸仓库中的当前分支,Git 不允许推送该分支:Git 拒绝更新远程工作目录。您真的应该只推送到裸仓库。对于非裸仓库,Git 更喜欢基于拉取的工作流程。

当您想在远程主机上部署代码并且只能使用推送(因为您的工作站位于防火墙后面,您无法从它拉取)时,您需要分两步使用两个仓库来完成:您从工作站推送到远程主机上的裸仓库,通过 ssh 连接到远程主机,然后从裸仓库拉取到非裸部署仓库。

这在 Git 2.3 中有所改变,但请参阅 这篇博客文章 了解注意事项;在 2.4 中,push-to-deploy 功能 进一步改进

标签

Git 在 fetch/pull 期间会自动获取指向正在获取的提交的标签。要获取所有标签(及其指向的提交),请运行 git fetch --tags origin。要获取某些特定标签,请显式获取它们

$ git fetch origin tag $TAG1 tag $TAG2...

例如

$ git fetch origin tag 1.4.2
$ git fetch origin v1:v1 tag 2.1.7

Git 不会自动推送标签。这允许您拥有私有标签。要推送标签,请明确列出它们

$ git push origin tag 1.4.2
$ git push origin v1 master tag 2.1.7

或者一次性推送所有标签

$ git push --tags origin

标签发布后,请勿使用 git tag -f 移动标签,或使用 git tag -d 删除标签。

私人信息

当克隆/获取/拉取/推送时,git 只复制数据库对象(提交、树、文件和标签)和符号引用(分支和轻量级标签)。其他一切都对仓库是私有的,从不克隆、更新或推送。这是您的配置、您的钩子、您的私有排除文件。

如果您想分发钩子,请将它们复制到工作树,添加、提交、推送,并指示团队手动更新和安装钩子。

提交编辑和注意事项

文档中也出现了关于不要编辑已发布(已推送)提交的警告,但鉴于其重要性,这里仍然重复一遍。

从强制推送中恢复是可能的,但这对于整个团队来说都是一个麻烦。请避免这样做。

要查看尚未发布的提交,请将分支的头部与其上游远程跟踪分支进行比较

$ git log origin/master..  # from origin/master to HEAD (of master)
$ git log origin/v1..v1  # from origin/v1 to the head of v1

对于每个具有上游远程跟踪分支的分支,Git 维护一个别名 @{upstream}(简写为 @{u}),因此上述命令可以表示为

$ git log @{u}..
$ git log v1@{u}..v1

查看所有分支的状态

$ git branch -avv

将本地分支状态与远程仓库进行比较

$ git remote show origin

阅读 如何从上游变基中恢复。它位于 git help rebase 中。

另一方面,不要太担心提交编辑。您可以安全地编辑、重新排序、删除、组合和拆分尚未推送的提交。您甚至可以将提交推送到您自己的(备份)仓库,稍后编辑它们并强制推送编辑过的提交以替换已推送的内容。只要提交不在公共或共享仓库中,就没问题。

撤消

无论你做什么,都不要惊慌。Git 中几乎所有操作都可以撤消。

git checkout:恢复文件内容

git checkout,例如,可以用来将文件内容恢复到某个提交。像这样

git checkout HEAD~ README

该命令将 README 文件的内容恢复到当前分支倒数第二个提交。默认情况下,提交 ID 只是 HEAD;即 git checkout README 将 README 恢复到最新提交。

(不要使用 git checkout 来查看提交中的文件内容,请使用 git cat-file -p;例如 git cat-file -p HEAD~:path/to/README)。

git reset:移除(未推送的)提交

git reset 移动当前分支的头部。头部可以移动到指向任何提交,但它通常用于从分支顶部删除一个或几个提交(最好是未推送的),即向后移动分支以撤消几个(未推送的)提交。

git reset 有三种操作模式——软、硬和混合。默认是混合模式。ProGit 解释了 它们之间的区别非常清楚。裸仓库没有索引或工作树,因此在裸仓库中只可能进行软重置。

取消暂存

带有路径的混合模式重置可用于取消暂存更改——即,从索引中移除使用 git add 添加的更改以进行提交。有关取消暂存和其他撤消技巧的详细信息,请参阅 《Pro Git》

git reflog:引用日志

使用 git reset 删除提交或移动分支的头部听起来很危险,确实如此。但有一种方法可以撤销:再次重置回原始提交。Git 不会立即删除提交;未引用的提交(在 Git 术语中称为“悬空提交”)会在数据库中停留一段时间(默认为两周),因此您可以重置回它或创建一个指向原始提交的新分支。

对于每次分支头部的移动——无论是通过 git commitgit checkoutgit fetchgit pullgit rebasegit reset 等等——Git 都会存储一个引用日志(简称 reflog)。对于每次移动,Git 都会存储头部所在的位置。git reflog 命令可用于查看(和操作)日志。

除了每个分支头部的移动之外,git 还存储 HEAD 的移动——这是一个符号引用,(通常)它表示当前分支。HEAD 通过 git checkout $BRANCH 进行更改。

默认情况下,git reflog 显示 HEAD 的移动,即该命令等效于 git reflog HEAD。要显示分支头部的移动,请使用命令 git reflog $BRANCH

因此,要撤消 git reset,请在 git reflog 中查找原始提交,使用 git showgit log 进行验证,然后运行 git reset $COMMIT_ID。Git 将分支头部的移动存储在 reflog 中,因此您以后可以再次撤消该撤消。

在更复杂的情况下,您可能希望在重置分支头部的同时移动一些提交。将它们樱桃挑选到新分支。例如,如果您想将 master 分支重置回原始提交,但保留当前分支中创建的两个提交,请执行类似操作

$ git branch save-master  # create a new branch saving master
$ git reflog  # find the original place of master
$ git reset $COMMIT_ID
$ git cherry-pick save-master~ save-master
$ git branch -D save-master  # remove temporary branch

git revert:回滚提交

git revert 会回滚一个或多个提交,也就是说,它会创建一个或多个新的提交来回滚给定提交的效果。这是撤消已发布提交的唯一方法(git commit --amendgit rebasegit reset 以非快进的方式更改分支,因此它们只应用于未推送的提交。)

回滚合并提交存在问题。git revert 可以撤消合并提交创建的代码,但它无法撤消合并的事实。请参阅讨论 如何回滚错误的合并

无法撤消的事情

无论您撤销什么,有一件事是无法撤销的——被覆盖的未提交更改。未提交的更改不属于 Git,因此 Git 无法帮助保留它们。

大多数情况下,当您要执行覆盖未提交更改的命令时,Git 会警告您。Git 不允许您使用 git checkout 切换分支。当您在工作区不干净的情况下要进行变基时,它会阻止您。它拒绝在未提交的文件上拉取新提交。

但是有些命令确实会这样做——覆盖工作树中的文件。像 git checkout $PATHsgit reset --hard 这样的命令会默默地覆盖文件,包括您的未提交更改。

考虑到这一点,您就可以理解“尽早提交,经常提交”的立场了。尽可能经常提交。在编辑器或 IDE 中每次保存时都提交。您可以在推送之前编辑您的提交——编辑提交消息,更改提交,重新排序,组合,拆分,删除。但请将您的更改保存在 Git 数据库中,要么提交更改,要么至少使用 git stash 将它们暂存起来。

合并还是变基?

互联网上充斥着关于“合并还是变基?”的激烈讨论。其中大多数毫无意义。当 DVCS 被用于一个庞大且复杂的项目、有许多分支的大型团队时,根本无法避免合并。因此问题缩小为“是否使用变基,如果使用,何时使用变基?”考虑到强烈建议不要对已发布的提交进行变基,问题进一步缩小为:“是否对未推送的提交使用变基?”

这个小问题由团队决定。为了保持线性历史的优美,建议在拉取时使用变基,即执行 git pull --rebase,甚至为每个新分支配置自动变基设置

$ git config branch.autosetuprebase always

并为现有分支配置变基

$ git config branch.$NAME.rebase true

例如

$ git config branch.v1.rebase true
$ git config branch.master.rebase true

此后,git pull origin master 等同于 git pull --rebase origin master

建议在单独的功能分支或主题分支中创建新提交,同时使用变基来更新主线分支。当主题分支准备好后,将其合并到主线。为了避免一次性解决大量冲突的繁琐任务,您可以不时将主题分支合并到主线,然后切换回主题分支继续在其上工作。整个工作流程将是这样的

$ git checkout -b issue-42  # create a new issue branch and switch to it
    ...edit/test/commit...
$ git checkout master
$ git pull --rebase origin master  # update master from the upstream
$ git merge issue-42
$ git branch -d issue-42  # delete the topic branch
$ git push origin master

当主题分支被删除时,只移除了标签,提交仍然保留在数据库中,它们现在已合并到 master 中

o--o--o--o--o--M--< master - the mainline branch
    \         /
     --*--*--*             - the topic branch, now unnamed

删除主题分支是为了避免用小主题分支弄乱分支命名空间。关于修复了什么问题或实现了什么功能的信息应该在提交消息中。

但即使是少量变基,对于长期合并的分支来说也可能太多。想象一下,您正在 v1master 分支中工作,定期将 v1 合并到 master。一段时间后,您将在 master 中拥有大量合并和非合并提交。然后您想将完成的工作推送到共享仓库,却发现有人向 v1 推送了几个提交。现在您有两种同样糟糕的选择:要么获取并变基 v1,然后不得不重新创建 master 中的所有工作(将 master 重置到 origin,合并 v1 并从旧的 master 中樱桃挑选所有非合并提交);要么合并新的 v1 并失去线性历史的优美。

空合并

Git 有一个内置的合并策略,用于 Python 核心开发者所称的“空合并”

$ git merge -s ours v1  # null-merge v1 into master

分支模型

Git 不假定任何特定的分支和合并开发模型。有些项目倾向于将补丁从最旧的分支升级到最新,有些倾向于反向樱桃选择提交,有些使用 squashing(将多个提交合并为一个)。一切皆有可能。

有一些例子可以作为起点。git help workflows 描述了 Git 作者如何开发 Git。

ProGit 书中有几章专门讨论不同项目中的分支管理:Git 分支 - 分支工作流分布式 Git - 贡献到项目

Vincent Driessen 还发表了一篇著名的文章 一个成功的 Git 分支模型。它推荐了一套非常详细的规则,用于创建和管理主线、主题和错误修复分支。为了支持该模型,作者实现了 git flow 扩展。

高级配置

行尾符

Git 内置机制可处理不同行尾样式平台之间的行尾问题。要让 Git 进行 CRLF 转换,请使用 .gitattributes 为文件分配 text 属性。对于必须具有特定行尾的文件,请分配 eol 属性。对于二进制文件,属性自然是 binary

例如

$ cat .gitattributes
*.py text
*.txt text
*.png binary
/readme.txt eol=CRLF

要检查 Git 为文件使用的属性,请使用 git check-attr 命令。例如

$ git check-attr -a -- \*.py

有用的资源

GitAlias仓库)是大量的别名集合。仔细选择常用命令的别名可以节省您大量的击键!

GitIgnorehttps://github.com/github/gitignore 是适用于各种 IDE 和编程语言的 .gitignore 文件集合。包括 Python!

pre-commit仓库)是一个用于管理和维护多语言 pre-commit 钩子的框架。该框架用 Python 编写,拥有许多用于多种编程语言的插件。

高级主题

暂存区

暂存区,又称索引或缓存,是 Git 的一个显著特性。暂存区是 Git 在提交补丁之前收集补丁的地方。收集补丁和提交阶段的分离提供了 Git 一个非常有用的功能:您可以在提交之前查看收集到的补丁,甚至可以编辑它们——删除一些代码块,添加新的代码块,然后再次查看。

要将文件添加到索引,请使用 git add。在提交之前收集补丁意味着您需要对每次更改都这样做,而不仅仅是添加新的(未跟踪的)文件。为了简化提交,如果您只想在不审查的情况下提交所有内容,请运行 git commit --all(或简写 -a)——该命令会将每个更改的已跟踪文件添加到索引,然后提交。要提交一个或多个文件,而不考虑索引中收集的补丁,请运行 git commit [--only|-o] -- $FILE...

要将补丁块添加到索引,请使用 git add --patch(或简写 -p)。要从索引中删除已收集的文件,请使用 git reset HEAD -- $FILE...。要添加/检查/删除已收集的补丁块,请使用 git add --interactive-i)。

要查看索引和上次提交之间的差异(即收集到的补丁),请使用 git diff --cached。要查看工作树和索引之间的差异(即未收集的补丁),请只使用 git diff。要查看工作树和上次提交之间的差异(即收集和未收集的补丁),请运行 git diff HEAD

参见 Git Wiki 中的 WhatIsTheIndexIndexCommandQuickref

根目录

Git 在运行任何命令之前会切换到根目录(项目顶层目录,其中包含 .git 子目录)。但 Git 会记住切换前所在的当前目录。有些程序会考虑当前目录。例如,git status 显示相对于当前目录的更改和未知文件的路径;git grep 在当前目录下方搜索;git apply 只应用补丁中影响当前目录下方文件的 hunk。

但大多数命令都是从根目录运行并忽略当前目录的。例如,假设您有两个工作树,一个用于 v1 分支,另一个用于 master。如果您想在第二个工作树内的子目录中合并 v1,您必须像在顶层目录中一样编写命令。例如,假设有两个工作树,project-v1project,例如

$ cd project/subdirectory
$ git fetch ../project-v1 v1:v1
$ git merge v1

请注意,在 git fetch ../project-v1 v1:v1 中,路径是 ../project-v1,而不是 ../../project-v1,尽管我们是从子目录而不是根目录运行命令。

ReReRe

Rerere 是一种帮助解决重复合并冲突的机制。重复合并冲突最常见的来源是将主题分支合并到主线中然后删除合并提交;这通常用于测试主题分支并训练 rerere;删除合并提交是为了拥有干净的线性历史,并以仅一个最终合并提交结束主题分支。

Rerere 的工作原理是记住成功提交前后树的状态。这样,如果冲突出现在相同的文件中,rerere 就可以自动解决它们。

Rerere 可以使用 git rerere 命令手动使用,但最常自动使用。在工作树中启用 rerere,使用以下命令

$ git config rerere.enabled true
$ git config rerere.autoupdate true

您不需要全局打开 rerere——您不需要在裸仓库或单分支仓库中使用 rerere;您只需要在经常执行合并和解决合并冲突的仓库中使用 rerere。

请参阅《Pro Git》中的 Rerere

数据库维护

Git 对象数据库和 .git 下的其他文件/目录需要定期维护和清理。例如,提交编辑会留下未引用的对象(在 Git 术语中称为悬空对象),这些对象应该被修剪以避免在数据库中堆积垃圾。命令 git gc 用于维护。Git 自动将 git gc --auto 作为某些命令的一部分运行,以进行快速维护。建议用户不时运行 git gc --aggressivegit help gc 建议每隔几百个变更集运行一次;对于更密集的项目,应该像每周一次,对于不那么活跃的项目则不那么频繁(每两周或每月一次)。

git gc --aggressive 不仅删除悬空对象,它还将对象数据库重新打包成索引和更优化的包;它还会打包符号引用(分支和标签)。另一种方法是运行 git repack

Linus Torvalds 有一则著名的 消息,关于 git gc --aggressive 的“愚蠢”。现在这条消息可以安全地忽略了。它已经过时了,从那时起 git gc --aggressive 已经变得好很多了。

对于那些仍然喜欢 git repack 而不是 git gc --aggressive 的人,推荐的参数是 git repack -a -d -f --depth=20 --window=250。有关这些参数影响的解释,请参阅 这个详细实验

不时运行 git fsck [--strict] 来验证数据库的完整性。git fsck 可能会生成一个悬空对象列表;这不是错误,只是提醒您进行定期维护。

技巧和窍门

命令行选项和参数

git help cli 建议不要组合短选项/标志。大多数情况下组合是有效的:git commit -av 完美运行,但有时不起作用。例如,git log -p -5 不能组合成 git log -p5

有些选项带有参数,有些甚至有默认参数。在这种情况下,此类选项的参数必须以粘连方式拼写:-Oarg,切勿 -O arg,因为对于具有默认参数的选项,后者表示“使用选项 -O 的默认值并将 arg 进一步传递给选项解析器”。例如,git grep 有一个选项 -O,它将找到的文件名列表传递给一个程序;-O 的默认程序是分页器(通常是 less),但您可以使用您的编辑器

$ git grep -Ovim  # but not -O vim

顺便说一句,如果 Git 被指示使用 less 作为分页器(即,如果 Git 中根本没有配置分页器,它默认使用 less,或者如果它从 GIT_PAGER 或 PAGER 环境变量中获取 less,或者如果它配置了 git config [--global] core.pager less,或者 less 在命令 git grep -Oless 中使用),git grep 会将 +/$pattern 选项传递给 less,这非常方便。不幸的是,如果分页器不是精确的 less,即使是带有参数的 less(例如 git config [--global] core.pager less -FRSXgimq),git grep 也不会传递模式;幸运的是,git grep -Oless 总是传递模式。

bash/zsh 补全

即使对于那些乐于使用命令行的人来说,手动键入 git rebase --interactive --preserve-merges HEAD~5 也有点困难,而这就是 shell 补全大有帮助的地方。Bash/zsh 带有可编程补全功能,通常会自动安装和启用,所以如果你安装了 bash/zsh 和 git,很可能你已经完成了——只需在命令行中使用它即可。

如果您没有安装必要的组件,请安装并启用 bash_completion 包。如果您想将 Git 补全升级到最新版本,请从 git contrib 下载必要的文件。

Git-for-windows 附带 git-bash,其中已安装并启用了 bash 补全。

bash/zsh 提示符

对于命令行爱好者来说,shell 提示符可以携带大量有用的信息。要将 Git 信息包含在提示符中,请使用 git-prompt.sh。请阅读文件中的详细说明。

在网上搜索“git prompt”以查找其他提示符变体。

SSH 连接共享

SSH 连接共享是 OpenSSH 以及 PuTTY 等衍生产品的一项功能。SSH 连接共享是一种通过建立一个连接并将其重用于连接到同一服务器的所有后续客户端来减少 ssh 客户端启动时间的方法。SSH 连接共享可用于加速大量短 ssh 会话,例如 scp、sftp、rsync,当然还有通过 ssh 的 Git。如果您经常从/向可通过 ssh 访问的远程仓库 fetch/pull/push,建议使用 ssh 连接共享。

要开启 SSH 连接共享,请在您的 ~/.ssh/config 中添加类似以下内容

Host *
ControlMaster auto
ControlPath ~/.ssh/mux-%r@%h:%p
ControlPersist 600

请参阅 OpenSSH wikibook搜索 了解更多信息。

SSH 连接共享可以在 GitHub、GitLab 和 SourceForge 仓库上使用,但请注意 BitBucket 不允许这样做,并在短时间不活动后强制关闭主连接,因此您会看到来自 ssh 的类似错误:“与 bitbucket.org 的连接被远程主机关闭。”

服务器上的 Git

发布仓库或一组仓库的最简单方法是 git daemon。该守护进程提供匿名访问,默认情况下是只读的。仓库可以通过 git 协议(git:// URL)访问。可以启用写入访问,但该协议缺少任何身份验证手段,因此只能在受信任的局域网内启用。有关详细信息,请参阅 git help daemon

通过 ssh 提供的 Git 提供了身份验证和仓库级别的授权,因为仓库可以设置为用户或组可写(参见 git help config 中的参数 core.sharedRepository)。如果这对于某些项目需求来说过于宽松或过于严格,可以使用封装器 gitolite,它可以配置为提供精细的访问控制;gitolite 用 Perl 编写,拥有大量文档。

可以使用 gitwebcgit 创建用于浏览仓库的 Web 界面。两者都是 CGI 脚本(分别用 Perl 和 C 编写)。除了 Web 界面,两者还为 Git 提供只读的简单 HTTP 访问(http(s):// URL)。Klaus 是一个小型简单的 WSGI Web 服务器,它实现了 Web 界面和 Git 智能 HTTP 传输;支持 Python 2 和 Python 3,并执行语法高亮。

还有更高级的基于网络的开发环境,包括管理用户、组和项目的功能;私有、组可访问和公共仓库;它们通常包括问题跟踪器、维基页面、拉取请求以及其他用于开发和通信的工具。这些环境包括 Kallitheapagure,两者都用 Python 编写;pagure 由 Fedora 开发者编写,并被用于开发一些 Fedora 项目。GitPrep 是另一个 GitHub 克隆,用 Perl 编写。Gogs 用 Go 编写。GitBucket 用 Scala 编写。

最后但同样重要的是,GitLab。它可能是 Git 最先进的基于 Web 的开发环境。用 Ruby 编写,社区版免费开源(MIT 许可证)。

从 Mercurial 到 Git

有许多工具可以将 Mercurial 仓库转换为 Git。最著名的可能就是 hg-gitfast-export(多年前它被称为 hg2git)。

但一个更好的工具,也许是最好的,是 git-remote-hg。它提供了从 Git 透明地双向(拉取和推送)访问 Mercurial 仓库。它的作者写了一篇 替代品比较,这看起来大部分是客观的。

要使用 git-remote-hg,请安装或克隆它,添加到您的 PATH(或将脚本 git-remote-hg 复制到已在 PATH 中的目录),并在 Mercurial URL 前面加上 hg::。例如

$ git clone https://github.com/felipec/git-remote-hg.git
$ PATH=$PATH:"`pwd`"/git-remote-hg
$ git clone hg::https://hg.python.org/peps/ PEPs

要使用仓库,只需使用常规的 Git 命令,包括 git fetch/pull/push

要开始将您的 Mercurial 习惯转换为 Git,请参阅 Mercurial wiki 上的页面 Mercurial for Git users。页面后半部分有一个表格,列出了相应的 Mercurial 和 Git 命令。应该在两个方向上都完美运行。

Python 开发者指南中也有一章 Mercurial for git developers,其中记录了 Git 和 hg 之间的一些区别。

Git 和 GitHub

gitsome - Git/GitHub 命令行界面 (CLI)。用 Python 编写,可在 MacOS、Unix、Windows 上运行。Git/GitHub CLI 具有自动补全功能,包括许多与所有 shell 配合使用的 GitHub 集成命令,内置带有 Python REPL 的 xonsh,可同时运行 Python 命令和 shell 命令,命令历史记录,可自定义高亮显示,文档详尽。


来源: https://github.com/python/peps/blob/main/peps/pep-0103.rst

最后修改: 2024-04-14 20:08:31 GMT