查看原文
其他

Gitless:试图将 Git 变得更容易理解

TJ君 TJ君 2021-05-26

早在几年前,MIT计算机科学和人工智能实验室的研究团队就为了让Git对用户来说更加友好更加方便使用,开发了Gitless,Gitless是基于Git的实现,用户无需迁移代码就能在两者之间切换。今天就为大家做一个简单的介绍Gitless。

Gitless有几个基本特点,大先了解下:

  • 可以简单处理提交工作流

    可以自动控制是否需要跟踪或取消跟踪文件的变化用来控制要提交的更改。默认情况下会提交对跟踪文件的更改,但也可以使用标志轻松自定义要提交的文件。

  • 独立的代码分支机构

    Gitless中的分支包含了各种开发上的更改,可以方便的在分支之间切换,而不必担心冲突的未提交更改。

  • 界面友好

    独有的Gitless命令行模式会给予用户良好的使用反馈指引下一步该做什么。

  • 与Git兼容

    因为Gitless是在Git基础上实现的,所以总是可以依赖Git。此外,可以将Gitless与GitHub或任何Git托管服务一起使用。

接口命令

  • gl init - 创建空的库或从现有的远程库中创建一个
  • gl status - 显示库里的状态
  • gl track - 开始跟踪文件更改
  • gl untrack - 停止跟踪对文件的更改
  • gl diff - 显示对文件的更改
  • gl commit - 在本地记录中记录提交更改
  • gl checkout - 取消提交
  • gl history - 显示提交的历史记录
  • gl branch - 列出、创建、编辑或删除分支
  • gl switch - 交换分支
  • gl tag - 列出、创建或删除标签
  • gl merge - 将一个分支的不同变化合并到另一个分支上
  • gl fuse -将一个分支的发散变化融合到另一个分支上
  • gl resolve - 将有冲突的文件标记为已解决
  • gl publish - 发布提交
  • gl remote - 列出、创建、编辑或删除远程

创建存储库

假设你在目录foo中,并且希望将其转换为存储库。你可以使用gl init命令执行此操作。这会将当前工作目录转换为空存储库,可以开始将更改保存到foo中的文件:

$ mkdir foo
cd foo/
$ gl init
✔ Local repo created in /MyFiles/foo

在大多数情况下,你不是从一个空的存储库开始,而是已经有一些你想要处理的现存的远程存储库。要克隆远程存储库,需要将存储库的URL传递给相同的gl init命令,如下所示(注意,必须替换https://github.com/gitless-vcs/try-gitless与你的记录地址):

$ mkdir try-gitless
cd try-gitless/
$ gl init https://github.com/gitless-vcs/try-gitless
✔ Local repo created in /MyFiles/try-gitless
✔ Initialized from remote https://github.com/gitless-vcs/try-gitless

如果你还没有远程存储库,可以按照这个说明在GitHub上创建一个。

保存更改

有了本地存储库,就要开始学习保存对文件的更改了。Gitless中的文件可以被跟踪、取消跟踪或忽略。跟踪文件是Gitless将自动检测文件,如果跟踪的文件被修改并显示在“已修改的跟踪文件”下,则会自动考虑提交这些文件。相反,未跟踪的文件是Gitless不会自动考虑提交,并显示在“未跟踪文件”部分下。最后,一个被忽略的文件是一个被Gitless完全忽略的文件,它甚至不会出现在清单里。

gl status命令的输出示例(foo.py和bar.py是经过修改的跟踪文件,.gitignore是未修改的跟踪文件,baz.py是一个未跟踪的文件,foo.pyc是被忽略的文件):

$ ls
bar.py  baz.py  foo.py  foo.pyc .gitignore
$ gl status
On branch master, repo-directory //

Tracked files with modifications:
  ➜ these will be automatically considered for commit
  ➜ use gl untrack <f> if you don't want to track changes to file f
  ➜ if file f was committed before, use gl checkout <f> to discard local changes

    foo.py
    bar.py

Untracked files:
  ➜ these won'
t be considered for commit)
  ➜ use gl track <f> if you want to track changes to file f

    baz.py

那么,文件如何在这三个不同的不相交状态之间切换??

如果文件与.gitinore文件中描述的ignore规范匹配,则忽略该文件。在上面的示例中,有一个.gitinore文件,其内容是“*.pyc”;因为foo.pyc与它匹配,因此它是一个被忽略的文件。

与忽略规范不匹配的新文件最初是未跟踪的文件。如果要跟踪它,可以使用gl track命令。可以使用gl untrack命令停止跟踪对跟踪文件的更改。始终可以使用gl checkout命令将文件恢复到以前的某个版本。

$ gl track baz.py
✔ File baz.py is now a tracked file
$ gl track baz.py
✘ File baz.py is already a tracked file
$ gl untrack baz.py
✔ File baz.py is now an untracked file
$ gl checkout foo.py
You have uncommitted changes in foo.py that would be
overwritten by checkout. Do you wish to continue? (y/N)
> y
✔ File foo.py checked out successfully to its state at HEAD

要保存对文件的更改,请使用gl commit。默认情况下,所有跟踪的修改文件都会考虑提交,但要提交的文件集可以通过仅列出要提交的文件或使用e/exclude和i/include标志进行自定义:

$ gl commit -m "foo and bar"
$ gl commit -m "only foo" foo.py
$ gl commit -m "only foo and baz" foo.py baz.py
$ gl commit -m "only foo" -e bar.py
$ gl commit -m "only foo and baz" -e bar.py -i baz.py
$ gl commit -m "foo, bar and baz" -i baz.py

还有一个p/partial标志,允许你以交互方式选择要提交的文件段。

gl diff命令可用于查看文件的工作版本和提交版本之间的差异。与commit类似,diff的默认文件集是所有跟踪的修改文件集,但可以通过列出文件或使用e/exclude和i/include标志进行自定义。

要删除文件,只需像在操作系统中那样执行(例如,使用Unix的rm命令)。如果文件被跟踪,Gitless将检测到更改,并且在状态中显示为已删除。Gitless当前未检测到重命名。如果你重命名一个文件,Gitless将把它解释为一个文件,旧名称被删除,新名称和内容被创建。如果要再次跟踪重命名的文件,则需要使用gl track对其进行跟踪。

分支

分支是一条独立的开发线。一般情况你总是在某个分支上工作。每个分支都有自己的历史记录(可以使用gl history命令查看)。切换分支时,对分支上创建的现有文件或新文件所做的任何更改都不会出现在其他分支上。

要创建新分支,请使用gl branch命令。要切换到其他分支,请使用gl switch命令:

$ gl branch -c develop
✔ Created new branch develop
$ gl switch develop
✔ Switched to branch develop

展示所有的分支:

$ gl branch
List of branches:
  ➜ do gl branch <b> to create branch b
  ➜ do gl branch -d <b> to delete branch b
  ➜ do gl switch <b> to switch to branch b
  ➜ * = current branch

    * master
      develop

每个分支都有一个头,就是在分支上完成的最后一次提交。默认情况下,新分支的头将等于当前分支的头。如果你希望一个不同的commit成为新分支的头,你可以为它提供dp/发散点标志。

要指定提交,可以使用它的id,也可以通过引用指定它,~:HEAD~n表示HEAD之前的第n个提交。

要更改当前分支的头,请使用sh/set head标志。例如,sh标志有助于修改上次提交:为此,运行gl branch-sh HEAD~1。如果你还想重置工作目录以匹配你使用的gl checkout的新头,那么更改当前分支的头将不会触及你的工作目录。

最终分支会有不同的变化。有两种方法可以将更改从一个分支引入当前分支:合并和融合。

合并分支。要将develop中的更改合并到当前分支上,需要执行gl merge develop。这将创建一个新的合并提交,除了当前分支中的更改外,还包括develop中的更改:


融合分支。融合分支比合并提供更多的控制。将某个分支的更改融合到当前分支时,可以指定要融合的提交和插入点。默认情况下,所有发散提交都是融合的,插入点是发散点(源分支从当前分支发散的点)。例如,下图描述了有两个分支的情况:master(当前分支)和develop。这两个分支共有的最后一个提交是A。这个提交是“发散点”(因为它是master和develop发散的点)。执行gl fuse develope后,develope中的提交将插入到发散点之后的master中:


要选择其他插入点,可以使用ip/insertion-point标志。你可以将提交id作为输入、头或dp/divergent-point:

fuse with insertion point specified

o/only和e/exclude标志可用于自定义要融合的提交集:

fuse with insertion point and commit specified

在此过程中可能会发生冲突。如果是这样,gl status命令将相应地更改,以指示存在冲突的文件。一旦你编辑了这些冲突的文件,你就可以用gl resolve将它们标记为已解决(将文件传递给标记为输入)。一旦所有的冲突都解决了,你就要执行gl commit 提交以继续使用fuse或merge。

一个分支可以有一个“上游分支”。如果一个分支有一个与之相关联的上游分支,那么gl fuse或gl merge可以用作gl{fuse,merge}上游分支的缩写。要为当前分支设置上游分支,请使用gl branch -su upstream_branch。

标记

使用标记表示提交在某种程度上是特殊的。例如,可以使用gl tag创建名为“v1.0”的标记,并使其指向表示版本v1.0的提交:

$ gl tag -c v1.0
✔ Created new tag v1.0

在这种情况下,标记将指向当前分支的头,但你可以使用ci/commit标志标记其他提交。

展现所有标记:

$ gl tag
List of tags:
  ➜ do gl tag <t> to create tag t
  ➜ do gl tag -d <t> to delete tag t

    v1.0 ➜  tags 311bf7c Ready to release

使用远程存储库

要引用远程存储库,你可以始终使用其URL,但更简单的替代方法是使用gl remote命令将存储库添加为“remote”:

$ gl remote -c try-gitless https://github.com/gitless-vcs/try-gitless
✔ Remote try-gitless mapping to https://github.com/gitless-vcs/try-gitless created
successfully
  ➜ to list existing remotes do gl remote
  ➜ to remove try-gitless do gl remote -d try-gitless

现在你可以使用try gitless来引用这个远程存储库,并使用try gitless/some branch来引用名为some branch的分支,该分支位于try gitless中。

下载更改。还可以融合或合并来自远程分支的更改。例如,执行gl merge try gitless/master将合并该远程分支中的更改,这些更改不在本地当前分支中。你也可以使用gl fuse.

上传更改。要向上游发送更改,请使用gl publish。如果没有输入,publish命令将默认更新当前分支的上游分支。

创建、删除或列出远程分支。要创建、删除或列出远程分支,请使用与本地分支相同的gl branch命令。如果你使用gl branch-c try gitless/develope,这将创建一个位于远程try gitless的分支develope。回想一下,默认情况下,这个新分支的头将等于当前分支的头,因此所有不在远程分支中的提交都将被上载。要列出远程分支,请使用gl branch的r/remote标志。

创建、删除或列出远程标记。要创建或删除远程标记,请使用gl tag命令。如果你使用gl tag-c try gitless/v1.0,这将创建一个新的标记v1.0,该标记位于远程try gitless中。你还可以使用gl tag的r/remote标志列出远程标记。

从远程创建本地存储库时(通过将URL作为输入传递到gl init命令),将为每个远程分支创建一个本地分支,并且每个本地分支将自动配置为具有其远程对应的上游分支。

Gitless vs. Git的对比

保存更改

Gitless没有中转站。这与灵活的commit命令相结合,使得将更改保存到存储库非常简单:

同样,你可以将任何文件的分类更改为“已跟踪”、“未跟踪”或“忽略”,不管文件是否存在于文件头:

分支

主要要理解的是,在Gitless中,分支是一条完全独立的开发线。每个分支将文件的工作版本彼此分开。每当你切换到另一个分支时,工作目录的内容都会被保存,并且与你要切换到的分支相对应的内容也会被检索。文件的分类也会被保存(即,一个文件可以在某个分支上被取消跟踪,但在另一个分支上被跟踪,Gitless会记住这一点):

这意味着在Gitless中,你不必担心未提交的更改与目标分支中的更改冲突:

如果你正处于融合/合并过程中,并且希望将冲突解决方案放在一边以备将来使用,那么你可以这样做。当你切换回时,冲突将出现:

使用远程存储库

在Gitless中与其他存储库同步的工作方式与Git非常相似:


往期推荐

80后记忆中的Gameboy,教你怎么用模拟器去重温旧梦!
好用!目前用下来最溜的MacOS微信多开工具!
受够996了吗?开源上岸指南来了!



大家好,我是TJ

一个励志推荐10000款开源项目与工具的程序员

欢迎关注我,了解更多牛x、有趣的东东


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存