「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,并且使用您自己的电子邮件地址替换 [email protected]。
# 通过输入 ~ 来进入你的主目录。
cd ~
git config --global --add user.name "Example Users"
git config --global --add user.email [email protected]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 <[email protected]>
Date: Sun Jan 01 00:00:30 2023 +0000
feats: add files
commit f112277...sha1
Author: Example Users <[email protected]>
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 <[email protected]>
Date: Sun Jan 01 00:00:00 2023 +0000
init: add My-Work-Report恭喜,你已经成功在 Git repo 中增加了文件,修改文件并且跟踪版本和上面是一样的,首先打开你最喜欢的编辑器修改文件。
echo "good report" >> My-Work-Report.txtgit 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 <[email protected]>
Date: Sun Jan 01 00:00:30 2023 +0000
feats: good report for My-Work-Report
commit f212277...sha1
Author: Example Users <[email protected]>
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 与它们所不同的是,它是一个多分支的版本管理系统,并且不需要服务器。
相关链接
喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!



- 来自作者
- 相关推荐