git拾遗

能够充分使用好一件工具的前提是知道它的原理。我已经忘记了自己多少次去查找git的教程了,每次觉得差不多了能满足当前的需求了就停止进一步的了解了。或许翻阅git的官方文档来学习是更好的选择。

Git tutorial

首先,我们从官网的tutorial开始。它主要介绍了git的常用命令和常用使用场景。

一些简单的常用命令

配置个人信息:

$ git config --global user.name "Your Name"
$ git config --global user.email ""Your Email"
  • git init:初始化文件夹,建立.git/数据库以使用git进行版本控制。
  • git log:查看简单的项目历史。
  • git branch "new_branch":建立新分支。
  • git switch "branch":切换分支。
  • git branch -D "branch":删除分支。
  • git branch -r:查看添加的远程分支。
  • gitk:打开图形化管理界面。
  • git checkout <tree-ish> -- <file>:如果给出tree-ish,那么会重置index和worktree。否则的话,从index中重置worktree。
  • git restore <file>:相当于git restore [--source=<tree-ish>] --staged <pathspec>,操作与git add相反。

使用Git进行合作

官网给出了一个使用情景:Bob在同一个服务器上想要和Alice合作。于是Bob输入了以下命令(我也是第一次知道可以本地合作,而且对一个git repo就可以直接clone了):

bob$ git clone /home/alice/project myrepo

Bob在自己的文件文件夹进行修改并使用commit提交到版本库后,通知Alice来拉取并合并修改的内容。Alice输入以下命令:

alice$ git pull /home/bob/myrepo master

这个操作能够在Alice没有修改内容的情况下,直接将两个repo进行合并。pull的操作包含两个部分:首先拉取远程分支中修改的部分,然后合并到当前分支中。所以git pull指令能够被人为地分为两个部分:git fetchgit merge

Alice可以先拉取远程分支,并查看哪些部分被修改过,最后再决定是否要合并。

alice$ git fetch /home/bob/myrepo master
alice$ git log -p HEAD..FETCH_HEAD

HEAD..FETCH_HEAD表示FETCH_HEAD能够到达的所有节点,并去除了HEAD也能访问到的节点。而HEAD...FETCH_HEAD表示了HEAD和FETCH_HEAD两方没有同时拥有的节点,也就是HEAD..FETCH_HEAD+FETCH_HEAD.._HEAD

为了和bob的库频繁交互,Alice使用git remote add bob /home/bob/myrepo将bob的库加入到本地的记录中,这样Alice就可以使用git fetch bob来拉取了,并通过git merge bob/master来合并了。

对象数据库

git使用object来对repo进行追踪。object一共有四个类型:commit,tree,blob和tag。可以使用git cat-file -t "obj"来检查object的类型。

commit指的是提交,git会生成一个object来表示每次提交,其中会记录提交的信息和修改的文件,而修改的文件是通过另外一个类型为tree的object记录的。

$ git cat-file -t HEAD
commit

$ git cat-file commit HEAD
tree 3d423aa4cf6f32514753cb14181b0cbbc9279134
author Euruson <[email protected]> 1661666189 +0800
committer Euruson <[email protected]> 1661666189 +0800

init the repo

tree是文件树,也就是一个文件夹下相关文件的快照,可以记录哪些文件被修改了。同时tree里可以嵌套其他的tree object来代表子文件夹。可以用git ls-tree "obj"来查看详细信息。

$ git ls-tree 3d423        
100644 blob dfe0770424b2a19faf507a501ebfc23be8f54e7b    .gitattributes
100644 blob 6361337690e02dbe51962b25f683768a5f6e7097    .gitignore
100644 blob 738fd84d975dcd7d660d609b5946a9e5d52225fc    LICENSE
100644 blob 20342e12331719464a26c3a95f3dcac6f6b3a7e4    README.md
040000 tree 7cc56d241934381f37ff655608b45ff4648cbb16    app
040000 tree 73dfeb483f87574616e06bb28f9598b9b6501d6f    conf
100644 blob e081de933960ee0d1a3ed194e4cc36d769855be9    fabfile.py
100644 blob 17b887bf60d44cbd5aec147444882bd584abe446    pymonitor.py

blob就是简单的数据文件,可以使用git cat-file blob "obj"来查看。

tag在tutorial中还没有细讲,之后有机会再补充。

暂存区

git中需要注意的有三个区域:工作区,暂存区和版本库。

工作区就是当前正在使用的工作目录。暂存区用来存储当前已完成并准备提交到版本库的内容。版本库记载了每一次提交的变化内容。

git工作区,暂存区和版本库

git status能够展示当前三个区域的简单情况。

git diff的用法可以用来比较三个区域的文件修改情况:

  • git diff比较工作目录和暂存区。
  • git diff HEAD比较工作目录和最后一次提交。
  • git diff --cached比较暂存区和最后一次提交。

暂存区除了存储将要提交的内容,也会在切出分支时被填充,这时它会包含一些与合并操作相关的tree。

Some tricks

一些odds and ends,虽然用的机会不多,但是依然很有用处。

将文件保留在库中,但不再追踪

假设网站有一个数据库配置文件db.php,通过git做版本控制,已经将这个文件提交到git库中。但是数据库配置不适合开源,但是有希望有个示范样例,所以希望这个db.php修改后在每次commit的时候不被提交。

通过.gitignore是无法办到的,.gitignore相当于将文件从库中删除,且不再追踪。

  • 加入不提交队列:git update-index --assume-unchanged db.php
  • 取消加入不提交队列:git update-index --no-assume-unchanged db.php

git拾遗

能够充分使用好一件工具的前提是知道它的原理。我已经忘记了自己多少次去查找git的教程了,每次觉得差不多了能满足当前的需求了就停止进一步的了解了。或许翻阅git的官方文档来学习是更好的选择。

Git tutorial

首先,我们从官网的tutorial开始。它主要介绍了git的常用命令和常用使用场景。

一些简单的常用命令

配置个人信息:

$ git config --global user.name "Your Name"
$ git config --global user.email ""Your Email"
  • git init:初始化文件夹,建立.git/数据库以使用git进行版本控制。
  • git log:查看简单的项目历史。
  • git branch "new_branch":建立新分支。
  • git switch "branch":切换分支。
  • git branch -D "branch":删除分支。
  • git branch -r:查看添加的远程分支。
  • gitk:打开图形化管理界面。
  • git checkout <tree-ish> -- <file>:如果给出tree-ish,那么会重置index和worktree。否则的话,从index中重置worktree。
  • git restore <file>:相当于git restore [--source=<tree-ish>] --staged <pathspec>,操作与git add相反。

使用Git进行合作

官网给出了一个使用情景:Bob在同一个服务器上想要和Alice合作。于是Bob输入了以下命令(我也是第一次知道可以本地合作,而且对一个git repo就可以直接clone了):

bob$ git clone /home/alice/project myrepo

Bob在自己的文件文件夹进行修改并使用commit提交到版本库后,通知Alice来拉取并合并修改的内容。Alice输入以下命令:

alice$ git pull /home/bob/myrepo master

这个操作能够在Alice没有修改内容的情况下,直接将两个repo进行合并。pull的操作包含两个部分:首先拉取远程分支中修改的部分,然后合并到当前分支中。所以git pull指令能够被人为地分为两个部分:git fetchgit merge

Alice可以先拉取远程分支,并查看哪些部分被修改过,最后再决定是否要合并。

alice$ git fetch /home/bob/myrepo master
alice$ git log -p HEAD..FETCH_HEAD

HEAD..FETCH_HEAD表示FETCH_HEAD能够到达的所有节点,并去除了HEAD也能访问到的节点。而HEAD...FETCH_HEAD表示了HEAD和FETCH_HEAD两方没有同时拥有的节点,也就是HEAD..FETCH_HEAD+FETCH_HEAD.._HEAD

为了和bob的库频繁交互,Alice使用git remote add bob /home/bob/myrepo将bob的库加入到本地的记录中,这样Alice就可以使用git fetch bob来拉取了,并通过git merge bob/master来合并了。

对象数据库

git使用object来对repo进行追踪。object一共有四个类型:commit,tree,blob和tag。可以使用git cat-file -t "obj"来检查object的类型。

commit指的是提交,git会生成一个object来表示每次提交,其中会记录提交的信息和修改的文件,而修改的文件是通过另外一个类型为tree的object记录的。

$ git cat-file -t HEAD
commit

$ git cat-file commit HEAD
tree 3d423aa4cf6f32514753cb14181b0cbbc9279134
author Euruson <[email protected]> 1661666189 +0800
committer Euruson <[email protected]> 1661666189 +0800

init the repo

tree是文件树,也就是一个文件夹下相关文件的快照,可以记录哪些文件被修改了。同时tree里可以嵌套其他的tree object来代表子文件夹。可以用git ls-tree "obj"来查看详细信息。

$ git ls-tree 3d423        
100644 blob dfe0770424b2a19faf507a501ebfc23be8f54e7b    .gitattributes
100644 blob 6361337690e02dbe51962b25f683768a5f6e7097    .gitignore
100644 blob 738fd84d975dcd7d660d609b5946a9e5d52225fc    LICENSE
100644 blob 20342e12331719464a26c3a95f3dcac6f6b3a7e4    README.md
040000 tree 7cc56d241934381f37ff655608b45ff4648cbb16    app
040000 tree 73dfeb483f87574616e06bb28f9598b9b6501d6f    conf
100644 blob e081de933960ee0d1a3ed194e4cc36d769855be9    fabfile.py
100644 blob 17b887bf60d44cbd5aec147444882bd584abe446    pymonitor.py

blob就是简单的数据文件,可以使用git cat-file blob "obj"来查看。

tag在tutorial中还没有细讲,之后有机会再补充。

暂存区

git中需要注意的有三个区域:工作区,暂存区和版本库。

工作区就是当前正在使用的工作目录。暂存区用来存储当前已完成并准备提交到版本库的内容。版本库记载了每一次提交的变化内容。

git工作区,暂存区和版本库

git status能够展示当前三个区域的简单情况。

git diff的用法可以用来比较三个区域的文件修改情况:

  • git diff比较工作目录和暂存区。
  • git diff HEAD比较工作目录和最后一次提交。
  • git diff --cached比较暂存区和最后一次提交。

暂存区除了存储将要提交的内容,也会在切出分支时被填充,这时它会包含一些与合并操作相关的tree。

Some tricks

一些odds and ends,虽然用的机会不多,但是依然很有用处。

将文件保留在库中,但不再追踪

假设网站有一个数据库配置文件db.php,通过git做版本控制,已经将这个文件提交到git库中。但是数据库配置不适合开源,但是有希望有个示范样例,所以希望这个db.php修改后在每次commit的时候不被提交。

通过.gitignore是无法办到的,.gitignore相当于将文件从库中删除,且不再追踪。

  • 加入不提交队列:git update-index --assume-unchanged db.php
  • 取消加入不提交队列:git update-index --no-assume-unchanged db.php


Powered by Mume Copyright © 2019-2022.

Euruson. All rights reserved.