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 用户手册大约 20 个命令的日常 GitGit 工作流程

高级文档

Git 魔法,有多种翻译版本。

Pro Git。关于 Git 的书籍。可在亚马逊购买或下载 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,会报告本地分支和远程分支之间的差异。请记住,它们只会与您本地仓库中的远程跟踪分支进行比较,并且这些远程跟踪分支的状态可能已过时。要更新远程跟踪分支,您可以从远程仓库获取并合并(或变基)提交,或者在不更新本地分支的情况下更新远程跟踪分支。

更新本地和远程跟踪分支

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

$ git remote update
$ git remote update origin

获取和拉取

以下两个命令之间存在主要区别

$ 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。当您运行

$ git push origin v1 master

Git 会将本地 v1 推送到远程 v1,并将本地 master 推送到远程 master。与以下命令相同

$ git push origin v1:v1 master:master

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

可以配置 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 中,推送部署功能得到了进一步改进

标签

Git 会自动获取在获取/拉取期间被获取的提交所指向的标签。要获取所有标签(以及它们指向的提交),请运行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添加以进行提交的更改。有关取消暂存和其他撤消技巧的详细信息,请参阅本书

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 中,因此您可以稍后再次撤消该撤消操作。

在更复杂的情况下,您可能希望在重置分支的头部时同时移动一些提交。将它们 cherry-pick 到新分支。例如,如果您想将分支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

建议在使用rebase更新主分支时,在单独的功能或主题分支中创建新的提交。当主题分支准备就绪时,将其合并到主分支。为了避免一次解决大量冲突的繁琐任务,您可以不时将主题分支合并到主分支,然后切换回主题分支继续处理它。整个工作流程类似于

$ 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

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

但即使是少量rebase,在长期合并分支的情况下也可能太大。假设您同时在v1master分支中工作,定期将v1合并到master中。一段时间后,您将在master中拥有大量的合并和非合并提交。然后,您想将完成的工作推送到共享存储库,并发现有人已将一些提交推送到v1。现在,您有两种同样糟糕的选择:要么获取并rebase v1,然后必须在master中重新创建所有工作(将master重置到origin,合并v1并从旧的master中cherry-pick所有非合并提交);或者合并新的v1并失去线性历史的美感。

空合并

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

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

分支模型

Git不会假设任何关于分支和合并的特定开发模型。一些项目更喜欢将补丁从最旧的分支升级到最新分支,一些项目更喜欢向后cherry-pick提交,一些项目使用压缩(将多个提交合并为一个)。任何事情都是可能的。

这里有一些示例可以开始使用。git help workflows描述了git作者如何开发git。

ProGit书籍专门介绍了不同项目中的分支管理章节:Git Branching - Branching WorkflowsDistributed Git - Contributing to a Project

还有一篇著名的文章,Vincent Driessen撰写的A successful Git branching model。它推荐了一套关于创建和管理主线、主题和修复分支的非常详细的规则。为了支持该模型,作者实现了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

有用资源

GitAliasrepository)是一个大型的别名集合。仔细选择常用命令的别名可以节省大量按键操作!

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

pre-commitrepositories)是一个用于管理和维护多语言提交前钩子的框架。该框架是用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仅应用补丁中触及当前目录下文件的那些块。

但是大多数命令都从根目录运行并忽略当前目录。例如,假设您有两个工作树,一个用于分支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。

请参阅《The Book》中的Rerere

数据库维护

Git对象数据库和.git下的其他文件/目录需要定期维护和清理。例如,提交编辑会留下未引用的对象(在git术语中称为悬空对象),这些对象应进行修剪,以避免在DB中收集垃圾。命令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 配置,或者在命令 git grep -Oless 中使用 less),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 访问的远程存储库中获取/拉取/推送,则建议使用 ssh 连接共享。

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

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

请参阅 OpenSSH wikibook搜索 以获取更多信息。

SSH 连接共享可用于 GitHub、GitLab 和 SourceForge 存储库,但请注意,BitBucket 不允许这样做,并且在短时间内活动后会强制关闭主连接,因此您会看到 ssh 的类似错误:“Connection to bitbucket.org closed by remote host.”

服务器上的 Git

发布存储库或一组存储库的最简单方法是 git daemon。守护进程提供匿名访问,默认情况下它是只读的。存储库可以通过 git 协议(git:// URL)访问。可以启用写入访问权限,但该协议没有任何身份验证方法,因此应仅在受信任的 LAN 中启用。有关详细信息,请参阅 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,执行语法高亮。

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

最后但并非最不重要的是,GitLab。它可能是最先进的基于 Web 的 Git 开发环境。用 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 集成命令,内置的 xonsh 带有 Python REPL 以在 Shell 命令旁边运行 Python 命令,命令历史记录,可自定义的高亮显示,文档齐全。


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

上次修改时间:2024-04-14 20:08:31 GMT