「Git 101」非程序员的版本控制
如何使用该文章
我们将超出基础的内容放在单独的部分,只对基础知识感兴趣的人来说,不要太分散注意力。 您可以自行决定是否要查看它们:
「了解更多」框包含一般附加信息:
了解更多 此类部分包含超出基础知识的内容,你可能会感觉有些挑战。
「底层细节」详细阐述了底层的技术细节:
底层细节:对于(未来)Git 专家
这里讨论了 Git 底层是如何实现,然而,你绝对不需要 Git 底层的知识,不过,您将在整个过程中遇到 Git 命令无法理解时,看看这里可能会有思路。
如果您是使用本机(即不是基于Windows Subsystem for Linux (WSL))安装 Git 的 Windows 用户,请密切注意所谓的「Windows 特殊情况」中的特别说明:
Windows 特殊情况:仅适用于 Windows 用户
某些文件系统,文件编码问题可能会影响 Git 在 Windows 上的行为。 如有必要,这里提供了问题的解决方法、解释,或者至少对这些不便表示歉意。
创建 Git repo
Git 是一个 DVCS (分布式版本控制系统),这里我们先不看这么奇怪的名词解释,首先要知道的就是版本控制。
我们的目标是通过一个简单的、现实生活中的示例来了解版本控制,能够让非程序员也能使用版本控制来管理文件。
假设您要做一个工作汇报,当你的领导确定最终使用的工作汇报前,你可能存储很多工作汇报。然后你的老板可能会说:还是使用第一个版本吧。这时候可能你的文件变成了这样。
如果您不使用 Git,您可能会尝试将文件用相同的规则来命名,来跟踪汇报的顺序(例如 My work report 09/09、My work report 09/10、My work report 09/11 0000、My work report 09/11 0100)等来构建自己的版本时间线。
每次您选择另存为并在文件夹中创建一个具有不同名称的新文档时,您都会在版本时间线中创建一个可以返回的快照(snapshots)。 例如,My-work-report 09-11-0100.docx 可以被视为下面的快照。
Git 模仿这个过程,并沿着明确的时间线组织您定义的快照,以便您可以按正确的顺序保留文档的不同版本并返回到以前的版本。
通过 Git 管理会是比复制更加安全,清晰并且占用空间可能会更小。
首先我们按照 datalad handbook 安装 Git。
然后我们进行初始配置。此操作只需执行一次。 在下面的例子中,用你自己的名字替换 Example Users
,并且使用您自己的电子邮件地址替换 users@example.com
。
# 通过输入 ~ 来进入你的主目录。
cd ~
git config --global --add user.name "Example Users"
git config --global --add user.email users@example.com
Windows 特殊情况:Unix-like 目录
Windows 中没有 ~ 目录,但
git config --global
不会因目录更改而变化。
此信息用于跟踪您在的 Git 项目中做了什么。 根据此信息,您所做的更改将被关联到您的姓名和电子邮件地址。不用担心,您不会收到来自 Git 的任何电子邮件。
现在,我们可以创建一个 git repo,只需要在你想要的位置输入。可选选项包含在 [ ]
。
git init [<directory>]
了解更多:
git init
的directory
选项是什么?可选的
directory
选项允许在非当前位置创建 git repo,例如git init ./directory
这将在当前目录下的
directory
目录创建 git repo。
了解更多:命令
与 shell 的交互采用命令的形式,即向计算机发送基于文本的指令。 命令区分大小写并遵循以下语法:
command [options...] <arguments...>
关于更多可以查看 datalad handbook
开始吧:
git init Git-Learn
这将在当前目录下的 Git-Learn
目录创建 git repo。
创建后,Git repo 看起来就像文件系统上的任何其它目录一样。 目前,它似乎是空的。
$ cd Git-Learn
$ ls # ls 没有任何输出,因为 Git repo 是空的。
Windows 特殊情况:Unix-like 命令
Windows 中没有 ls 命令,作为替代,Windows 使用 dir。
了解更多:神秘的
.git
文件夹如果你的文件浏览器没有隐藏文件,或者你使用
ls -a
你可能会看到。$ ls -a # show also hidden files . .. .git
你可能会好奇这个
.git
文件是从哪里来的,这个.git
文件是所有 Git 魔法发挥作用所必需的。 请不要修改它们,更重要的是,不要删除它们。
当然如果你如果想让当前目录不被 Git 管理,那么你可以删除它。
但是,您存储在 Git repo 中的所有文件和目录都可以被跟踪(如果您希望它们被跟踪)。
跟踪意味着对文件所做的编辑会自动与相关的更改,编辑的作者,以及变化的时间关联。 这本身就已经很重要了,例如,寻找文件的出处。但特别有用的是文件或目录的之前版本可以恢复。 这些信息存储在我们所说的 Git repo 的历史中。
$ git log
commit 20f3824...sha1 (HEAD -> master)
Author: Example Users <users@example.com>
Date: Sun Jan 01 00:00:30 2023 +0000
feats: add files
commit f112277...sha1
Author: Example Users <users@example.com>
Date: Sun Jan 01 00:00:00 2023 +0000
init: init commit
这段历史在当前状态下几乎是最小的,但让我们看一下。 为了查看历史记录,代码示例将使用 git log
(手册),您可以使用箭头键上下滚动,但如果不能输入任何命令,您可以按 q 退出 git log
。
恭喜,您刚刚创建了第一个 Git Repo! 现在让我们在里面添加一些内容。
在 Git repo 中增加一些内容
以之前我们说的,工作汇报来演示。你在 Git repo 中创建了一个新的工作汇报文件。
touch My-Work-Report.txt
echo "first line" > My-Work-Report.txt
当然你也可以使用你喜欢的文件管理器和编辑器来修改文件。
这时我们运行 git log
,会发现 fatal: your current branch 'master' does not have any commits yet
,如果你没有提交(commit)的话 Git 是不会记录你的更改到版本历史中的,这里的错误是因为我们甚至没有提交一次,如果你想看到我们当前目录和 Git 中的区别,可以使用 git status
。
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
My-Work-Report.txt
nothing added to commit but untracked files present (use "git add" to track)
它告诉了我们下一步要做什么,那么让我们立即使用 git add
。
git add My-Work-Report.txt
让我们再次使用 git status
。
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: My-Work-Report.txt
现在让我们立即提交一次。
git commit
这将打开你的编辑器,修改标题保存退出后就会提交。
另外,你也可以在 commit
命令后添加 -m
选项,将提交信息与命令放在同一行。
$ git commit -m "init: add My-Work-Report"
[master (root-commit) f212277] init: add My-Work-Report
1 file changed, 1 insertion(+)
create mode 100644 My-Work-Report.txt
这时我们运行 git log
,就会发现我们的文件已经在 Git repo 历史中了。
$ git log
commit f212277...sha1 (HEAD -> master)
Author: Example Users <users@example.com>
Date: Sun Jan 01 00:00:00 2023 +0000
init: add My-Work-Report
恭喜,你已经成功在 Git repo 中增加了文件,修改文件并且跟踪版本和上面是一样的,首先打开你最喜欢的编辑器修改文件。
echo "good report" >> My-Work-Report.txt
git add
并且提交它。
$ git add My-Work-Report.txt
$ git commit -m "feats: good report for My-Work-Report"
[master 21f3824] feats: good report for My-Work-Report
1 file changed, 2 insertions(+), 1 deletion(-)
这时我们再运行 git log
,就会发现我们已经有了两个 Git repo 历史记录。
$ git log
commit 21f3824...sha1 (HEAD -> master)
Author: Example Users <users@example.com>
Date: Sun Jan 01 00:00:30 2023 +0000
feats: good report for My-Work-Report
commit f212277...sha1
Author: Example Users <users@example.com>
Date: Sun Jan 01 00:00:00 2023 +0000
init: add My-Work-Report
这时,如果你的老板不认为你的第二版是个好报告的话,你可能会问我该如何将第一版取出,让我们使用 git restore
git restore [--source=<tree>] <pathspec>…
这里的 source
是我们上面 git log
看到的 sha1 编码,所以我们只需要运行。
git restore --source=f212277 My-Work-Report.txt
这个时候我们再查看 My-Work-Report.txt 中的文件,就已经变为第一版的时候了。
$ cat My-Work-Report.txt
first line
幸好,你的老板没否认你的辛苦努力,所以让我们把这个文件变回第二版。
git restore My-Work-Report.txt
当我们不给 source
参数时,它始终将我们的文件变为最新提交的文件上(git log
看到的最新一条)。
了解更多:HEAD 的位置
其实这个命令是将文件变为
HEAD
指向的提交位置,但由于我们始终没有自己更改过HEAD
,它就会在我们当前分支最新的提交上。
当我们的合并(merge)遇到冲突时,以及手动git reset
时,才会更改HEAD
的位置。
了解更多:恢复
git add
的更改有时你错误
git add
了一个文件,或者你根本不想提交这个更改,这时我们也可以用git restore
来取消更改。git restore [--source=<tree>] [--staged] [--worktree] <pathspec>…
这里我们通过指定
staged
参数来要求git restore
恢复git add
中的更改,也就是 stage 中。
如果我们不指定 source,默认是更改变成HEAD
中的版本。
如果我们不指定staged
参数,默认是worktree
参数,就是恢复我们在文件夹中的更改,也就是 working directory 中。
了解更多:工作目录、暂存区域以及 Git 仓库
我们这里提到了工作目录(working directory)、暂存区域(staging area)以及 Git 仓库(Git directory)。这是基于 Git 的三种状态,你的文件可能处于其中之一:已提交(committed)、已修改(modified) 和已暂存(staged)。
已修改表示修改了文件,但还没保存到数据库中。就是你编辑后的文件。
已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。就是
git add
后的文件。已提交表示数据已经安全地保存在本地数据库中。就是
git commit
后的文件。这会让我们的 Git 项目拥有三个阶段:工作区、暂存区以及 Git 目录。
基本的 Git 工作流程如下:
在工作区(working directory)中修改文件。
将你想要下次提交的更改选择性地暂存(
git add
),这样只会将更改的部分添加到暂存区(staging area)。提交(commit)更新,找到暂存区的文件,将快照永久性存储到 Git 目录(Git directory)。
你可能会觉得这样很复杂,但这样我们可以选择性地提交(commit)文件,比如我们可以第一次将 My-Work-Report.txt 加入 Git repo 中,第二次将 Boss-Work-Report.txt 加入 Git repo 中。但我们的工作区(working directory)在第一次提交(commit)后仍然存在 Boss-Work-Report.txt。
了解更多:
git reset
和git restore
你可能看到过有些地方(甚至 Git 也会推荐你)使用
git reset
,它们的功能你可能会觉得有些相似。
是的,它们在某些方面有些重合,但git reset
显得更加底层,需要你了解HEAD
的工作方式,并且了解soft
,mixed
,hard
这几种参数分别修改了什么。
但对比git restore
,它使用了更加明确的参数,staged
,worktree
,让你明白当前在修改什么。
此外,git restore
比较新,Git 手册会提示你这个命令是试验性的,其行为可能会改变
好了,你已经了解如何在 Git repo 中增加,修改文件和恢复文件的版本了。
可能你会觉得这种版本控制其实其它软件也能做到,是的,如果你使用 Windows 的文件历史,macOS 的 Time machine,或者是网络储存的版本历史,你可能会觉得非常熟悉,但 Git 与它们所不同的是,它是一个多分支的版本管理系统,并且不需要服务器。
相关链接
喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!
- 来自作者
- 相关推荐