我尝试将【Git】的“.git”文件夹交给Git进行管理

首先

2023年Git圣诞日历的第三天帖子。请多多关照。
我认为在上次和前次的帖子中,已经能够使用以下命令了。

    • git init

 

    • git add

 

    • git commit

 

    • git branch

 

    • git checkout

 

    git merge

我对内部的操作感到好奇,所以这次我想观察一下执行上述命令时.git文件夹内部的变化。

完成的任务

我们将按照下面的感觉继续进行。

创建存储库(A)

在存储库(A)的.git文件夹中运行git init来创建管理.git的存储库(B)

在存储库(A)处运行Git命令以观察存储库(B)中的差异

由于我使用了两个Git仓库,所以可能会有一些转换不太明显的地方,请多包涵。

准备

    • 「git/sample2」フォルダを用意。

 

    このフォルダでGitの各コマンドを打って.gitの中身を観察していきます。

初始化 Git

执行git init命令来创建存储库(A)的.git文件夹。

~/Desktop/git/sample2
$ git init
Initialized empty Git repository in フォルダ名

.gitフォルダの構成

.git
│  config
│  description
│  HEAD
│
├─hooks
│      applypatch-msg.sample
│      commit-msg.sample
│      fsmonitor-watchman.sample
│      post-update.sample
│      pre-applypatch.sample
│      pre-commit.sample
│      pre-push.sample
│      pre-rebase.sample
│      pre-receive.sample
│      prepare-commit-msg.sample
│      update.sample
│
├─info
│      exclude
│
├─objects
│  ├─info
│  └─pack
└─refs
    ├─heads
    └─tags

在.git文件夹中使用git init命令创建一个仓库(B)。

~/Desktop/git/sample2/.git (GIT_DIR!)
$ git init
Initialized empty Git repository in フォルダ名

~/Desktop/git/sample2/.git (master)
$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        HEAD
        config
        description
        hooks/
        info/

nothing added to commit but untracked files present (use "git add" to track)

~/Desktop/git/sample2/.git (master)
$ git add .

~/Desktop/git/sample2/.git (master)
$ git commit -m"git init後"
[master (root-commit) a47036c] git init

使用git add命令

在(A)仓库中创建一个名为“sample.txt”的文件。

~/Desktop/git/sample2 (master)
$ echo "hello world" > sample.txt

~/Desktop/git/sample2 (master)
$ ls
sample.txt

创建文件后的.git文件夹没有任何特殊变化。

~/Desktop/git/sample2/.git (master)
$ git status
On branch master
nothing to commit, working tree clean

我尝试执行git add。

~/Desktop/git/sample2 (master)
$ git add .

在使用 git add 之后的 .git 文件夹。

~/Desktop/git/sample2/.git (master)
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        index
        objects/

nothing added to commit but untracked files present (use "git add" to track)

哦,有了变化呢。

.gitフォルダの現在の状況

C:.
│  config
│  description
│  HEAD
│  index ←←←新規
│
├─hooks
│      applypatch-msg.sample
│      commit-msg.sample
│      fsmonitor-watchman.sample
│      post-update.sample
│      pre-applypatch.sample
│      pre-commit.sample
│      pre-push.sample
│      pre-rebase.sample
│      pre-receive.sample
│      prepare-commit-msg.sample
│      update.sample
│
├─info
│      exclude
│
├─objects
│  ├─3b ←←←新規
│  │      18e512dba79e4c8300dd08aeb37f8e728b8dad
│  │
│  ├─info
│  └─pack
└─refs
    ├─heads
    └─tags

与.git文件夹相比,可以看出在git init后,新创建了index和objects下的3b/18e512…。由于index是一个二进制文件,很难验证差异,因此最后将在附注中进行解释。

让我们来看一看对象的内容。

~/Desktop/git/sample2 (master)
$ git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
hello world

在Git添加时会生成一个blob对象。
我只知道这些。

提交代码

我接下来尝试提交一次。

~/Desktop/git/sample2 (master)
$ git commit -m"first commit"
[master (root-commit) 411124e] first commit

我会尝试在.git中执行git status。

~/Desktop/git/sample2/.git (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   index

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        COMMIT_EDITMSG
        logs/
        objects/02/
        objects/88/
        refs/

no changes added to commit (use "git add" and/or "git commit -a")

.git文件夹内容有所改变。指的是整个.git文件夹。

.git
│  COMMIT_EDITMSG ←←新規
│  config
│  description
│  HEAD
│  index ←←更新
│
├─hooks
│      applypatch-msg.sample
│      commit-msg.sample
│      fsmonitor-watchman.sample
│      post-update.sample
│      pre-applypatch.sample
│      pre-commit.sample
│      pre-push.sample
│      pre-rebase.sample
│      pre-receive.sample
│      prepare-commit-msg.sample
│      update.sample
│
├─info
│      exclude
│
├─logs ←←新規
│  │  HEAD
│  │
│  └─refs
│      └─heads
│              master
│
├─objects
│  ├─02 ←←新規
│  │      3bd50171db535beab09fed56bd5a9281b01555
│  │
│  ├─3b
│  │      18e512dba79e4c8300dd08aeb37f8e728b8dad
│  │
│  ├─88 ←←新規
│  │      ccc6b27fbf7beb37e2b2dadceef08ed83a5716
│  │
│  ├─info
│  └─pack
└─refs
    ├─heads
    │      master ←←新規
    │
    └─tags

我们逐个来看一下。

首先,由于生成了两个对象,所以我会查看它们的内容。

~/Desktop/git/sample2 (master)
$ git cat-file -p 88ccc6b27fbf7beb37e2b2dadceef08ed83a5716
100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad    sample.txt

~/Desktop/git/sample2 (master)
$ git cat-file -p 023bd50171db535beab09fed56bd5a9281b01555
tree 88ccc6b27fbf7beb37e2b2dadceef08ed83a5716
author hogehoge <fugafuga> 1699592736 +0900
committer hogehoge <fugafuga> 1699592736 +0900

first commit

我们可以看到树对象和提交对象已经生成。我们还可以看到树对象具有对Blob的引用,而提交对象具有对树对象的引用。

接下来我们看一下COMMIT_EDITMSG。

$ cat COMMIT_EDITMSG
first commit

这是之前提交的提交消息吗?目前为止,我不知道更多的信息。
我们稍后再试一次提交,看看是否会有变化。

让我们接着看看refs/heads/master。

$ cat refs/heads/master
023bd50171db535beab09fed56bd5a9281b01555

这个是指在objects文件夹中新创建的提交对象的哈希值。

最后是logs/HEAD和logs/refs/master。

$ cat logs/HEAD
0000000000000000000000000000000000000000 023bd50171db535beab09fed56bd5a9281b01555 hogehoge <fugafuga> 1699592736 +0900  commit (initial): first commit

$ cat logs/refs/heads/master
0000000000000000000000000000000000000000 023bd50171db535beab09fed56bd5a9281b01555 hogehoge <fugafuga> 1699592736 +0900  commit (initial): first commit

日志就像它的名字一样,用来存储记录。每个日志都记录了HEAD从哪个提交到哪个提交移动,以及分支从哪个提交到哪个提交移动。由于这次没有对分支进行特别操作,所以看起来内容是相同的。

因为我在意COMMIT_EDITMSG的处理方式,所以让我们再次进行提交吧。随意更新”sample.txt”并重新提交。

~/Desktop/git/sample2 (master)
$ echo "hello" > sample.txt

~/Desktop/git/sample2 (master)
$ git add .

~/Desktop/git/sample2 (master)
$ git commit -m"second commit"
[master 6cf4fd0] second commit
 1 file changed, 1 insertion(+), 1 deletion(-)

对于.git会怎么样呢?我试试看git status。

~/Desktop/git/sample2/.git (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   COMMIT_EDITMSG
        modified:   index
        modified:   logs/HEAD
        modified:   logs/refs/heads/master
        modified:   refs/heads/master

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        objects/6c/
        objects/ce/
        objects/e3/

no changes added to commit (use "git add" and/or "git commit -a")

先来看看我们想看的COMMIT_EDITMSG文件的差异。

~/Desktop/git/sample2/.git (master)
$ git diff COMMIT_EDITMSG
diff --git a/COMMIT_EDITMSG b/COMMIT_EDITMSG
index 44e4d81..2ff0cc0 100644
--- a/COMMIT_EDITMSG
+++ b/COMMIT_EDITMSG
@@ -1 +1 @@
-first commit
+second commit

看起来好像是保存着前一个提交信息的文件。
我想你已经猜到了,我们是否也应该查看其他文件呢?
这是当前的.git文件夹的情况。

.git
│  COMMIT_EDITMSG ←←←更新
│  config
│  description
│  HEAD
│  index ←←←更新
│
├─hooks
│      applypatch-msg.sample
│      commit-msg.sample
│      fsmonitor-watchman.sample
│      post-update.sample
│      pre-applypatch.sample
│      pre-commit.sample
│      pre-push.sample
│      pre-rebase.sample
│      pre-receive.sample
│      prepare-commit-msg.sample
│      update.sample
│
├─info
│      exclude
│
├─logs
│  │  HEAD ←←←更新
│  │
│  └─refs
│      └─heads
│              master ←←←更新
│
├─objects
│  ├─02
│  │      3bd50171db535beab09fed56bd5a9281b01555
│  │
│  ├─3b
│  │      18e512dba79e4c8300dd08aeb37f8e728b8dad
│  │
│  ├─6c ←←←新規
│  │      f4fd07bd3d1f982045f50fae9dc070d6967f36
│  │
│  ├─88
│  │      ccc6b27fbf7beb37e2b2dadceef08ed83a5716
│  │
│  ├─ce ←←←新規
│  │      013625030ba8dba906f756967f9e9ca394464a
│  │
│  ├─e3 ←←←新規
│  │      d14d7340059b5852f32f29574e98ff73eb3c47
│  │
│  ├─info
│  └─pack
└─refs
    ├─heads
    │      master
    │
    └─tags

objectsフォルダ配下の新規作成されたファイル3つ

~/Desktop/git/sample2 (master)
$ git cat-file -p ce013625030ba8dba906f756967f9e9ca394464a
hello

~/Desktop/git/sample2 (master)
$ git cat-file -p e3d14d7340059b5852f32f29574e98ff73eb3c47
100644 blob ce013625030ba8dba906f756967f9e9ca394464a    sample.txt

~/Desktop/git/sample2 (master)
$ git cat-file -p 6cf4fd07bd3d1f982045f50fae9dc070d6967f36
tree e3d14d7340059b5852f32f29574e98ff73eb3c47
parent 023bd50171db535beab09fed56bd5a9281b01555
author hogehoge <fugafuga> 1699594574 +0900
committer hogehoge <fugafuga> 1699594574 +0900

second commit

这是关于Blob、Tree和Commit对象的内容。

logsフォルダ配下の更新されたファイルの差分

~/Desktop/git/sample2/.git (master)
$ git diff logs/
diff --git a/logs/HEAD b/logs/HEAD
index 8783cde..58d6c1d 100644
--- a/logs/HEAD
+++ b/logs/HEAD
@@ -1,2 +1,2 @@
 0000000000000000000000000000000000000000 023bd50171db535beab09fed56bd5a9281b01555 hogehoge <fugafuga> 1699592736 +0900 commit (initial): first commit
+023bd50171db535beab09fed56bd5a9281b01555 6cf4fd07bd3d1f982045f50fae9dc070d6967f36 hogehoge <fugafuga> 1699594574 +0900 commit: second commit
diff --git a/logs/refs/heads/master b/logs/refs/heads/master
index 8783cde..58d6c1d 100644
--- a/logs/refs/heads/master
+++ b/logs/refs/heads/master
@@ -1,2 +1,2 @@
 0000000000000000000000000000000000000000 023bd50171db535beab09fed56bd5a9281b01555 hogehoge <fugafuga> 1699592736 +0900 commit (initial): first commit
+023bd50171db535beab09fed56bd5a9281b01555 6cf4fd07bd3d1f982045f50fae9dc070d6967f36 hogehoge <fugafuga> 1699594574 +0900 commit: second commit

日志是这样写的。

refs配下の更新されたファイルの差分

~/Desktop/git/sample2/.git (master)
$ git diff refs/
diff --git a/refs/heads/master b/refs/heads/master
index f1bb341..ed3d53b 100644
--- a/refs/heads/master
+++ b/refs/heads/master
@@ -1 +1 @@
-023bd50171db535beab09fed56bd5a9281b01555
+6cf4fd07bd3d1f982045f50fae9dc070d6967f36

主分支的提交已经移动了。

分支

接下来,让我们使用git branch命令创建一个分支。
我们将创建另一个分支。

~/Desktop/git/sample2 (master)
$ git branch another

.git文件夹里面发生了什么?

~/Desktop/git/sample2/.git (master)
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        logs/refs/heads/another
        refs/heads/another

nothing added to commit but untracked files present (use "git add" to track)

我们做了两个文件,请看一下。

$ cat refs/heads/another
6cf4fd07bd3d1f982045f50fae9dc070d6967f36

$ cat logs/refs/heads/another
0000000000000000000000000000000000000000 6cf4fd07bd3d1f982045f50fae9dc070d6967f36 hogehoge <fugafuga> 1699595907 +0900  branch: Created from master

参考/ブランチ/another 指向与 master 相同的提交。
我会查看日志以确认。

~/Desktop/git/sample2 (master)
$ git log --oneline
6cf4fd0 (HEAD -> master, another) second commit
023bd50 first commit

切换分支

那么,让我们尝试使用git checkout切换分支。
我将切换到另一个分支。

~/Desktop/git/sample2 (master)
$ git checkout another
Switched to branch 'another'

~/Desktop/git/sample2 (another)

现在.git会怎么样呢?

~/Desktop/git/sample2/.git (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   HEAD
        modified:   logs/HEAD

no changes added to commit (use "git add" and/or "git commit -a")

看到了吧,HEAD和logs/HEAD已经更新了。我试着取出它们的差异。

HEADファイル

~/Desktop/git/sample2/.git (master)
$ git diff HEAD -- HEAD
diff --git a/HEAD b/HEAD
index cb089cd..b64c555 100644
--- a/HEAD
+++ b/HEAD
@@ -1 +1 @@
-ref: refs/heads/master
+ref: refs/heads/another

刚刚创建的refs/heads/another文件已被更新以引用它。当然,这是理所当然的,因为HEAD已被更新为引用another。
再次强调一下,refs/heads/another的内容如下所示。

$ cat refs/heads/another
6cf4fd07bd3d1f982045f50fae9dc070d6967f36

从这个问题中,HEAD会持续指向另一个分支的提交6cf4fd。

logs/HEADファイル

~/Desktop/git/sample2/.git (master)
$ git diff HEAD -- logs/HEAD
diff --git a/logs/HEAD b/logs/HEAD
index 58d6c1d..9bb9ffe 100644
--- a/logs/HEAD
+++ b/logs/HEAD
@@ -1,2 +1,3 @@
 0000000000000000000000000000000000000000 023bd50171db535beab09fed56bd5a9281b01555 hogehoge <fugafuga> 1699592736 +0900 commit (initial): first commit
 023bd50171db535beab09fed56bd5a9281b01555 6cf4fd07bd3d1f982045f50fae9dc070d6967f36 hogehoge <fugafuga> 1699594574 +0900 commit: second commit
+6cf4fd07bd3d1f982045f50fae9dc070d6967f36 6cf4fd07bd3d1f982045f50fae9dc070d6967f36 hogehoge <fugafuga> 1699596443 +0900 checkout: moving from master to another

这是关于HEAD引用的日志对吧。是这样记录日志的方式。

将git合并

最后,我们将进行git merge,然后观察.git文件夹。

做好準備

由于准备工作很繁琐,我们将准备和观察的步骤分开了。首先,作为准备工作,我们在另一个分支上创建了一个适当的提交。

~/Desktop/git/sample2 (another)
$ echo "another" > sample.txt

~/Desktop/git/sample2 (another)
$ git add .

~/Desktop/git/sample2 (another)
$ git commit -m"third commit"
[another cbc33d4] third commit
 1 file changed, 1 insertion(+), 1 deletion(-)

.git文件夹的状态。没有什么特别值得注意的地方,所以先进行提交。

~/Desktop/git/sample2/.git (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   COMMIT_EDITMSG
        modified:   index
        modified:   logs/HEAD
        modified:   logs/refs/heads/another
        modified:   refs/heads/another

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        objects/11/
        objects/9b/
        objects/cb/

no changes added to commit (use "git add" and/or "git commit -a")

~/Desktop/git/sample2/.git (master)
$ git add .

~/Desktop/git/sample2/.git (master)
$ git commit -m"git commit 1回目@another"
[master d25acad] git commit 1回目@another

这次将切换到主分支master。

~/Desktop/git/sample2 (another)
$ git checkout master
Switched to branch 'master'

.git文件夹的状态。

~/Desktop/git/sample2/.git (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   HEAD
        modified:   index
        modified:   logs/HEAD

no changes added to commit (use "git add" and/or "git commit -a")

~/Desktop/git/sample2/.git (master)
$ git add .

~/Desktop/git/sample2/.git (master)
$ git commit -m"git checkout後another→master"
[master c15e8de] git checkout後another→master
 3 files changed, 2 insertions(+), 1 deletion(-)

由于从另一个分支更新文件的状态回到了原始的主分支,因此,“index”也被更新了。

合并

(Maaji)

好的,我现在要將另一個分支合併到主分支上試試看。

~/Desktop/git/sample2 (master)
$ git merge --no-ff another
Merge made by the 'recursive' strategy.
 sample.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

.git文件夹的状态。

(The state of the .git folder.)

~/Desktop/git/sample2/.git (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   index
        modified:   logs/HEAD
        modified:   logs/refs/heads/master
        modified:   refs/heads/master

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        ORIG_HEAD
        objects/bb/

no changes added to commit (use "git add" and/or "git commit -a")

让我们来看看,一个新的ORIG_HEAD和对象被生成了。

$ cat ORIG_HEAD
6cf4fd07bd3d1f982045f50fae9dc070d6967f36

我不记得这是哪个哈希值了…所以我来查看一下日志。

~/Desktop/git/sample2 (master)
$ git cat-file -p 6cf4fd07bd3d1f982045f50fae9dc070d6967f36
tree e3d14d7340059b5852f32f29574e98ff73eb3c47
parent 023bd50171db535beab09fed56bd5a9281b01555
author hogehoge <fugafuga> 1699594574 +0900
committer hogehoge <fugafuga> 1699594574 +0900

second commit

~/Desktop/git/sample2 (master)
$ git log --oneline --graph
*   bb54bb5 (HEAD -> master) Merge branch 'another'
|\
| * cbc33d4 (another) third commit
|/
* 6cf4fd0 second commit
* 023bd50 first commit

ORIG_HEAD所引用的6cf4fd是主分支(master)的直前提交,所以通过git reset ORIG_HEAD –hard命令可以回到合并之前的状态。

新产生的对象是什么内容呢?

MINGW64 ~/Desktop/git/sample2 (master)
$ git cat-file -p bb54bb567fc99a85750561362e2dcd892f179434
tree 11982c20951b8249234a871fb7fce5983fe1465f
parent 6cf4fd07bd3d1f982045f50fae9dc070d6967f36
parent cbc33d4a1844fddc6f4dad5918897d00a6eaa80f
author hogehoge <fugafuga> 1699598971 +0900
committer hogehoge <fugafuga> 1699598971 +0900

Merge branch 'another'

这个合并提交是引用了两个父对象的对象,对吧。

由于浏览其他文件会感到厌烦,所以我只会查看个人感兴趣的logs目录下的文件。

~/Desktop/git/sample2/.git (master)
$ git diff logs/
diff --git a/logs/HEAD b/logs/HEAD
index c43111f..eb4e0a5 100644
--- a/logs/HEAD
+++ b/logs/HEAD
@@ -4,3 +4,4 @@
 6cf4fd07bd3d1f982045f50fae9dc070d6967f36 6cf4fd07bd3d1f982045f50fae9dc070d6967f36 hogehoge <fugafuga> 1699596443 +0900 checkout: moving from master to another
 6cf4fd07bd3d1f982045f50fae9dc070d6967f36 cbc33d4a1844fddc6f4dad5918897d00a6eaa80f hogehoge <fugafuga> 1699598305 +0900 commit: third commit
 cbc33d4a1844fddc6f4dad5918897d00a6eaa80f 6cf4fd07bd3d1f982045f50fae9dc070d6967f36 hogehoge <fugafuga> 1699598624 +0900 checkout: moving from another to master
+6cf4fd07bd3d1f982045f50fae9dc070d6967f36 bb54bb567fc99a85750561362e2dcd892f179434 hogehoge <fugafuga> 1699598971 +0900 merge another: Merge made by the 'recursive' strategy.
diff --git a/logs/refs/heads/master b/logs/refs/heads/master
index 58d6c1d..1256f4a 100644
--- a/logs/refs/heads/master
+++ b/logs/refs/heads/master
@@ -1,2 +1,3 @@
 0000000000000000000000000000000000000000 023bd50171db535beab09fed56bd5a9281b01555 hogehoge <fugafuga> 1699592736 +0900 commit (initial): first commit
 023bd50171db535beab09fed56bd5a9281b01555 6cf4fd07bd3d1f982045f50fae9dc070d6967f36 hogehoge <fugafuga> 1699594574 +0900 commit: second commit
+6cf4fd07bd3d1f982045f50fae9dc070d6967f36 bb54bb567fc99a85750561362e2dcd892f179434 hogehoge <fugafuga> 1699598971 +0900 merge another: Merge made by the 'recursive' strategy.

日志不会这么写的。

竞合 hé)

如果竞争使用,会发生什么呢?
我将在主文件和另一个文件中随意进行编辑。

説明:masterブランチでファイルを編集
~/Desktop/git/sample2 (master)
$ echo "master" > sample.txt

~/Desktop/git/sample2 (master)
$ git add .

~/Desktop/git/sample2 (master)
$ git commit -m"fourth commit"
[master 61dd6f5] fourth commit
 1 file changed, 1 insertion(+), 1 deletion(-)

説明:anotherブランチでファイルを編集
~/Desktop/git/sample2 (master)
$ git checkout another
Switched to branch 'another'

~/Desktop/git/sample2 (another)
$ echo "another branch" > sample.txt

~/Desktop/git/sample2 (another)
$ git add .

~/Desktop/git/sample2 (another)
$ git commit -m"fifth commit"
[another bd61df7] fifth commit
 1 file changed, 1 insertion(+), 1 deletion(-)

説明:masterブランチでマージするので移動
~/Desktop/git/sample2 (another)
$ git checkout master
Switched to branch 'master'

现在的感觉就像这样。

~/Desktop/git/sample2 (master)
$ git log --graph --oneline --all
* bd61df7 (another) fifth commit
| * 61dd6f5 (HEAD -> master) fourth commit
| *   bb54bb5 Merge branch 'another'
| |\
| |/
|/|
* | cbc33d4 third commit
|/
* 6cf4fd0 second commit
* 023bd50 first commit

好吧,我来合并并竞争它们。

~/Desktop/git/sample2 (master)
$ git merge --no-ff another
Auto-merging sample.txt
CONFLICT (content): Merge conflict in sample.txt
Automatic merge failed; fix conflicts and then commit the result.

竞合了。.git文件夹怎么样了呢?

 ~/Desktop/git/sample2/.git (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   ORIG_HEAD
        modified:   index

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        MERGE_HEAD
        MERGE_MODE
        MERGE_MSG
        objects/7a/

no changes added to commit (use "git add" and/or "git commit -a")

我们来看一下刚刚合并时生成的文件,那些在之前没有的。让我们查看MERGE_HEAD、MERGE_MODE和MERGE_MSG的内容。

$ cat MERGE_HEAD
bd61df78647648b52c932db29880eda9f0e6b72f

$ cat MERGE_MODE
no-ff

$ cat MERGE_MSG
Merge branch 'another'

# Conflicts:
#       sample.txt

MERGE_HEAD指的是将要合并的分支的最新提交(在此例中是another分支的最新提交)。

由于生成了以7a开头的对象,我们来看一下它的内容。

~/Desktop/git/sample2 (master)
$ git cat-file -p 7a67e00d6b7bee74c0f0ebdd167f22400ea80f9b
<<<<<<< HEAD
master
=======
another branch
>>>>>>> another

对吧,一旦竞合,就会生成一个diff格式的对象。

下一个更新将是ORIG_HEAD。
与先前相同,指的是合并之前的提交。

~/Desktop/git/sample2/.git (master)
$ git diff ORIG_HEAD
diff --git a/ORIG_HEAD b/ORIG_HEAD
index ed3d53b..6eb6ba5 100644
--- a/ORIG_HEAD
+++ b/ORIG_HEAD
@@ -1 +1 @@
-6cf4fd07bd3d1f982045f50fae9dc070d6967f36
+61dd6f56c96d9a3edef66cce619cf2915d76205e

如果中止(abort)操作,.git文件夹会怎么样呢?
中止(abort)后的.git文件夹状态将会是以下的样子。

~/Desktop/git/sample2/.git (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    MERGE_HEAD
        deleted:    MERGE_MODE
        deleted:    MERGE_MSG
        modified:   index
        modified:   logs/HEAD

no changes added to commit (use "git add" and/or "git commit -a")

这些文件已经消失了,而且即使合并完成也可能会消失。

在模拟前面的竞争之后,现在我们将解决竞争并进行合并。
省略了竞争的模拟。↓从竞争发生到解决竞争的过程。

~/Desktop/git/sample2 (master|MERGING)
$ git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)

        both modified:   sample.txt

no changes added to commit (use "git add" and/or "git commit -a")

~/Desktop/git/sample2 (master|MERGING)
$ git diff
diff --cc sample.txt
index 1f7391f,5d70384..0000000
--- a/sample.txt
+++ b/sample.txt
@@@ -1,1 -1,1 +1,5 @@@
++<<<<<<< HEAD
 +master
++=======
+ another branch
++>>>>>>> another

~/Desktop/git/sample2 (master|MERGING)
$ echo "master" > sample.txt

~/Desktop/git/sample2 (master|MERGING)
$ git add .

~/Desktop/git/sample2 (master|MERGING)
$ git commit
[master 8254984] Merge branch 'another'

通过解决竞合问题,我们成功进行了合并提交。

「.git」文件夹的状态是这样的。

 ~/Desktop/git/sample2/.git (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   COMMIT_EDITMSG
        deleted:    MERGE_HEAD
        deleted:    MERGE_MODE
        deleted:    MERGE_MSG
        modified:   index
        modified:   logs/HEAD
        modified:   logs/refs/heads/master
        modified:   refs/heads/master

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        objects/82/

no changes added to commit (use "git add" and/or "git commit -a")

–与abort相同,MERGE_HEAD、MERGE_MODE、MERGE_MSG均已消失。

此外,已经生成了合并提交的对象。

~/Desktop/git/sample2 (master)
$ git cat-file -p 8254984b906f193d27c2e4f55ee75991155bcedf
tree d9fd303cfe17e779b06fe84c97c970ba22253c4b
parent 61dd6f56c96d9a3edef66cce619cf2915d76205e
parent bd61df78647648b52c932db29880eda9f0e6b72f
author hogehoge <fugafuga> 1699601812 +0900
committer hogehoge <fugafuga> 1699601812 +0900

Merge branch 'another'

以上是今天关于将“.git”管理成“Git”的演示的结束。
感谢大家一直阅读到最后。

有关「index」文件的补充说明

以下是关于一直被顽固地忽视的索引文件的补充说明。

索引文件是一个二进制文件,因此我们停止了观察,但顾名思义,索引文件是用于表示索引状态的二进制文件。它与树对象类似,具有树引用、文件名和数据块的对应关系。

将索引文件的创建和更新总结如下:

git add:初回のみindex作成、その後は更新

git commit:index更新

git branch:なにもなし

git checkout:なにもなし

git merge:index更新

当执行git add命令时,索引文件会被更新,并在git commit时创建树对象。换句话说,执行git add命令时,树对象不会被创建,只会更新索引文件。在git commit时,树对象会被创建,并且会用索引的内容进行替换。通过这样做,可以确保执行git add时工作目录和索引的内容一致,在执行git commit时,工作目录、索引和存储库的内容一致。

最后

我一边输入命令一边写文章,但途中出错并修改了部分命令结果后才发表出来,所以如果有细微错误的地方请原谅。

广告
将在 10 秒后关闭
bannerAds