• 主页
  • 相册
  • 随笔
  • 目录
  • 存档
Total 244
Search AboutMe

  • 主页
  • 相册
  • 随笔
  • 目录
  • 存档

git笔记

2020-01-27

1. 历史

  • 本地版本控制系

  • 集中化版本控制

  • 分布式版本控制

1.1. 区别

Git 保存的不是文件的变化或者差异,而是一系列不同时刻的文件快照


Git 更像是把数据看作是对小型文件系统的一组快照。
每次你提交更新,或在 Git 中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。
为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件

1.2. 特点

  • 在 Git 中的绝大多数操作都只需要访问本地文件和资源,一般不需要来自网络上其它计算机的信息

  • Git 中所有数据在存储前都计算校验和,然后以校验和来引用。这意味着不可能在 Git 不知情时更改任何文件内容或目录内容

2. 状态

2.1. 三个工作区域

  • Git 仓库

    • Git 用来保存项目的元数据和对象数据库的地方
  • 工作目录

    • 对项目的某个版本独立提取出来的内容r
  • 暂存区域

    • 一个文件,保存了下次将提交的文件列表信息,一般在 Git 仓库目录中。有时候也被称作“索引”

3. 初始配置

git config

  • 设置你的用户名称与邮件地址。每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改

    1
    2
    $ git config --global user.name "John Doe"
    $ git config --global user.email johndoe@example.com
  • 设置文本编辑器:git config --global core.editor emacs

  • 检查配置信息:git config --list

4. 帮助信息

  • git <verb> --help

  • git help <verb>

5. 获取 Git 仓库

  • 获取 Git 仓库:git init

  • 克隆现有的仓库:git clone

    • --depth=1:只克隆最近一次commit
      • 要把之前的历史重新再pull下来:git pull --unshallow

        A shallow repository (one with short history) cannot be further cloned


        unshallow:
        Convert a shallow repository to a complete one, removing all the limitations imposed by shallow repositories.
        非浅层转换为完整的存储库,消除浅层存储库所施加的所有限制

6. 文件状态

6.1. 种类

6.2. 检查当前文件状态

1
2
3
$ git status
On branch master
nothing to commit, working directory clean

6.3. 暂存已修改文件

git add

这是个多功能命令:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。将这个命令理解为“添加内容到下一次提交中”而不是“将一个文件添加到项目中”要更加合适

7. 查看提交历史

git log

默认不用任何参数的话,git log会按提交时间列出所有的更新,最近的更新排在最上面。这个命令会列出每个提交的 SHA-1 校验和、作者的名字和电子邮件地址、提交时间以及提交说明


一个常用的选项是 -p,用来显示每次提交的内容差异。 你也可以加上 -2 来仅显示最近两次提交

常用选项

-p

显示每次提交的内容差异。可以加上-2来仅显示最近两次提交

--stat

在每次提交的下面列出所有被修改过的文件、有多少文件被修改了以及被修改过的文件的哪些行被移除或是添加

更多参考

8. 撤消操作

8.1. 覆盖提交信息

提交后发现忘记了暂存某些需要的修改,可以像下面这样操作

1
2
3
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend

8.2. 取消暂存的文件

use git reset HEAD <file>... to unstage,取消暂存

  • git reset --soft HEAD^

8.3. 撤消对文件的修改(检出)

use git checkout -- <file>... to discard changes in working directory,撤消修改——将它还原成上次提交时的样子(或者刚克隆完的样子,或者刚把它放入工作目录时的样子)

9. 多commit信息

  • 需要分批次的add和commit

10. 远程仓库

10.1. 查看远程仓库

1
2
3
$ git remote -v
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push)

10.2. 添加远程仓库

git remote add <shortname> <url>

10.3. 从远程仓库中抓取与拉取

$ git fetch [remote-name]

这个命令会访问远程仓库,从中拉取所有你还没有的数据。 执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看


如果你使用 clone 命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以 “origin” 为简写。 所以,git fetch origin 会抓取克隆(或上一次抓取)后新推送的所有工作。 必须注意 git fetch 命令会将数据拉取到你的本地仓库——它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作

git pull

自动的抓取然后合并远程分支到当前分支。默认情况下,git clone 命令会自动设置本地 master 分支跟踪克隆的远程仓库的 master 分支(或不管是什么名字的默认分支)。 运行 git pull 通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支

10.3.1. 处理本地冲突

1
2
3
4
5
6
7
8
9
10
11
$(old_branch) git fetch new_branch
$(old_branch) git checkout new_branch
# no confilct
$(new_branch) git merge old_branch
# conflic
$(new_branch) git merge --strategy-option theirs
# if not work
git status
$(new_branch) git checkout <ref to theirs> -- the/conflicted.file
(git checkout --theirs path/of/file)
$(new_branch) git add .

10.4. 推送到远程仓库

git push [remote-name] [branch-name]

当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先将他们的工作拉取下来并将其合并进你的工作后才能推送

10.5. 远程仓库的移除与重命名

git remote rename

修改远程仓库的简写名

git remote rm

移除远程仓库

10.6. 多个远程仓库

1
2
3
4
5
git remote add github git@github.com:usr/repo.git
git remote add gitee git@gitee.com:usr/repo.git
git remote -v
git push github master
git push gitee master

11. 标签

11.1. 列出标签

git tag

11.2. 创建标签

  • 附注标签

    1
    2
    3
    4
    5
    $ git tag -a v1.4 -m "my version 1.4"
    $ git tag
    v0.1
    v1.3
    v1.4
    • -m 选项指定了一条将会存储在标签中的信息。如果没有为附注标签指定一条信息,Git 会运行编辑器要求你输入信息
    • 通过使用 git show 命令可以看到标签信息与对应的提交信息
  • 轻量标签:$ git tag v1.4-lw

    • 轻量标签本质上是将提交校验和存储到一个文件中——没有保存任何其他信息
    • 这时,如果在标签上运行 git show,你不会看到额外的标签信息
  • 后期打标签

    现在,假设在 v1.2 时你忘记给项目打标签,也就是在 “updated rakefile” 提交。 你可以在之后补上标签。要在那个提交上打标签,你需要在命令的末尾指定提交的校验和(或部分校验和)

    1
    $ git tag -a v1.2 9fceb02

默认标签是打在最新提交的commit上的

11.3. 共享标签

默认情况下,git push 命令并不会传送标签到远程仓库服务器上。 在创建完标签后你必须显式地推送标签到共享服务器上。 这个过程就像共享远程分支一样——你可以运行git push origin [tagname]

1
$ git push origin v1.5

12. Git 分支

12.1. 对象

当使用 git commit 新建一个提交对象前,Git 会先计算每一个子目录(本例中就是项目根目录)的校验和,然后在 Git 仓库中将这些目录保存为树(tree)对象


多个提交对象之间的链接关系

12.2. 指针

Git 中的分支,其实本质上仅仅是个指向 commit 对象的可变指针。Git 会使用 master 作为分支的默认名字。在若干次提交后,你其实已经有了一个指向最后一次提交对象的 master 分支,它在每次提交的时候都会自动向前移动


创建一个新的分支,相当于创建一个新的分支指针。比如新建一个 testing 分支,可以使用 git branch 命令 git branch testing 这会在当前 commit 对象上新建一个分支指针


Head 指针

  • 一个指向你正在工作中的本地分支的指针(译注:将 HEAD 想象为当前分支的别名。)。注意运行 git branch 命令,仅仅是建立了一个新的分支,但不会自动切换到这个分支中去
  • 要切换到其他分支,可以执行 git checkout <branch> 命令
  • 每次提交后 HEAD 随着分支一起向前移动

12.3. 分叉(diverged)

因为刚才我们创建了一个分支,转换到其中进行了一些工作,然后又回到原来的主分支进行了另外一些工作

12.4. 分支的新建

git checkout -b <branch>

  • 这相当于执行下面这两条命令
    • git branch <branch>
    • git checkout <branch>

12.5. 分支的删除

使用git branch的 -d选项执行删除操作

12.6. 分支合并

运行git merge命令指定要合并进来的分支

  • Fast forward

    请注意,合并时出现了“Fast forward”的提示。由于当前 master 分支所在的提交对象是要并入的 hotfix 分支的直接上游,Git 只需把 master 分支指针直接右移。换句话说,如果顺着一个分支走下去可以到达另一个分支的话,那么 Git 在合并两者时,只会简单地把指针右移,因为这种单线的历史分支不存在任何需要解决的分歧,所以这种合并过程可以称为快进(Fast forward)

  • Auto-merging

    请注意,这次合并操作的底层实现,并不同于之前 hotfix 的并入方式。因为这次你的开发历史是从更早的地方开始分叉的。由于当前 master 分支所指向的提交对象(C4)并不是 iss53 分支的直接祖先,Git 不得不进行一些额外处理。就此例而言,Git 会用两个分支的末端(C4 和 C5)以及它们的共同祖先(C2)进行一次简单的三方合并计算。图 3-16 用红框标出了 Git 用于合并的三个提交对象

    Git 对三方合并后的结果重新做一个新的快照,并自动创建一个指向它的提交对象(C6)

12.6.1. 遇到冲突时的分支合并

  • 逻辑上说,这种问题只能由人来裁决

  • 要看看哪些文件在合并时发生冲突,可以用 git status 查阅

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ git status
    On branch master
    You have unmerged paths.
    (fix conflicts and run "git commit")

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

    both modified: index.html

    no changes added to commit (use "git add" and/or "git commit -a")
  • Git 会在有冲突的文件里加入标准的冲突解决标记,可以通过它们来手工定位并解决这些冲突, 例如

    1
    2
    3
    4
    5
    6
    7
    <<<<<<< HEAD
    <div id="footer">contact : email.support@github.com</div>
    =======
    <div id="footer">
    please contact us at support@github.com
    </div>
    >>>>>>> iss53
  • 修改后可以再次用git status查看

12.7. 分支的管理

  • git branch命令如果不加任何参数,它会给出当前所有分支的清单。 当前所在的分支会用*标记。

    1
    2
    3
    4
    $ git branch
    iss53
    * master
    testing
  • --merged查看哪些分支已被并入当前分支

    一般来说,列表中没有 * 的分支通常都可以用git branch -d来删掉。原因很简单,既然已经把它们所包含的工作整合到了其他分支,删掉也不会损失什么。

  • --no-merged查看尚未合并的工作

12.8. 利用分支进行开发的工作流程

仅在 master 分支中保留完全稳定的代码,即已经发布或即将发布的代码。与此同时,创建 develop 或 next 的平行分支,专门用于后续的开发


特性(Topic)分支是指一个短期的,用来实现单一特性或与其相关工作的分支


流水线

12.9. 远程分支

  • 表示: (远程仓库名)/(分支名)

  • 一次 Git 克隆会建立你自己的本地分支 master 和远程分支 origin/master,并且将它们都指向 origin 上的 master 分支

  • 裸克隆

    • Another difference between a bare and non-bare repository is that a bare repository does not have a default remote origin repository
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      ~/Projects$ git clone --bare test bare
      Initialized empty Git repository in /home/derek/Projects/bare/
      ~/Projects$ cd bare
      ~/Projects/bare$ git branch -a
      * master
      ~/Projects/bare$ cd ..
      ~/Projects$ git clone test non-bare
      Initialized empty Git repository in /home/derek/Projects/non-bare/.git/
      ~/Projects$ cd non-bare
      ~/Projects/non-bare$ git branch -a
      * master
      remotes/origin/HEAD -> origin/master
      remotes/origin/master
  • clone操作基本上相当于 git init 加 git fetch

  • 同步: 可以运行git fetch origin来同步远程服务器上的数据到本地

    该命令首先找到 origin 是哪个服务器,从上面获取你尚未拥有的数据,更新你本地的数据库,然后把 origin/master 的指针移到它最新的位置上


    多个远程分支

  • 推送本地分支 git push (远程仓库名) (分支名)

    例如git push origin serverfix中, Git 自动把 serverfix 分支名扩展为 refs/heads/serverfix:refs/heads/serverfix,意为“取出我在本地的 serverfix 分支,推送到远程仓库的 serverfix 分支中去”。 也可以运行 git push origin serverfix:serverfix 来实现相同的效果,它的意思是“上传我本地的 serverfix 分支到远程仓库中去,仍旧称它为 serverfix 分支”

  • 跟踪: 从远程分支 checkout 出来的本地分支,称为 跟踪分支 (tracking branch)

    在克隆仓库时,Git 通常会自动创建一个名为 master 的分支来跟踪 origin/master。这正是 git push 和 git pull 一开始就能正常工作的原因。当然,你可以随心所欲地设定为其它跟踪分支,比如 origin 上除了 master 之外的其它分支。例如git checkout --track origin/serverfix

    • -u <host>: 指定host为默认主机, 之后就可以不加任何参数使用git push了
    • –all <host>: 不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机。 即将所有本地分支都推送到host主机
    • --tags: git push不会推送标签(tag),除非使用–-tags选项
  • 删除:

    如果不再需要某个远程分支了,比如搞定了某个特性并把它合并进了远程的 master 分支(或任何其他存放稳定代码的分支),可以用这个非常无厘头的语法来删除它:git push [远程名] :[分支名]。如果想在服务器上删除 serverfix 分支,运行命令git push origin :serverfix。 记住我们不久前见过的 git push [远程名] [本地分支]:[远程分支]语法,如果省略 [本地分支],那就等于是在说“在这里提取空白然后把它变成[远程分支]”。

12.10. This branch cannot be rebased due to conflicts

1
2
3
4
5
6
7
8
9
10
git checkout master
git fetch all
git pull --rebase upstream master
git checkout your_working_branch
git rebase origin/master
code . //打开vscode解决
git add .
git commit -m ""
git rebase --continue
git push -f origin your_working_branch:your_working_branch

13. 协议

13.1. 分类

简介优点缺点
本地协议最基本的就是本地协议(Local protocol),所谓的远程仓库在该协议中的表示,就是硬盘上的另一个目录。 克隆的时候只需要将远程仓库的路径作为 URL 使用, 比如git clone file:///opt/git/project.git。 如果在 URL 开头明确使用 file:// ,那么 Git 会以一种略微不同的方式运行。如果你只给出路径,Git 会尝试使用硬链接或直接复制它所需要的文件。如果使用了 file:// ,Git 会调用它平时通过网络来传输数据的工序,而这种方式的效率相对较低。简单,同时保留了现存文件的权限和网络访问权限, 通常会比他们推送到服务器,而你再从服务器获取简单得多难以控制从不同位置来的访问权限
SSH 协议SSH 也是唯一一个同时支持读写操作的网络协议。另外两个网络协议(HTTP 和 Git)通常都是只读的, 架设起来也很容易。 不指明某个协议 — 这时 Git 会默认使用 SSH git clone user@server:project.git, 或显式通过 SSH git clone ssh://user@server/project.git拥有对网络仓库的写权限, 架设相对比较简单, 通过 SSH 进行访问是安全的 — 所有数据传输都是加密和授权的, SSH 也很高效,会在传输之前尽可能压缩数据不能通过它实现仓库的匿名访问。即使仅为读取数据,人们也必须在能通过 SSH 访问主机的前提下才能访问仓库,这使得 SSH 不利于开源的项目
Git 协议一个包含在 Git 软件包中的特殊守护进程; 它会监听一个提供类似于 SSH 服务的特定端口(9418),而无需任何授权Git 协议是现存最快的传输协议Git 协议消极的一面是缺少授权机制。用 Git 协议作为访问项目的唯一方法通常是不可取的。一般的做法是,同时提供 SSH 接口,让几个开发者拥有推送(写)权限,其他人通过 git:// 拥有只读权限。 同时 Git 协议可能也是最难架设的协议。它要求有单独的守护进程,需要定制, 该协议还要求防火墙开放 9418 端口,而企业级防火墙一般不允许对这个非标准端口的访问。大型企业级防火墙通常会封锁这个少见的端口
HTTPS 协议HTTP 或 HTTPS 协议的优美之处在于架设的简便性。基本上,只需要把 Git 的裸仓库文件放在 HTTP 的根目录下,配置一个特定的 post-update 挂钩(hook)就可以搞定。 每个能访问 Git 仓库所在服务器上 web 服务的人都可以进行克隆操作。使用 HTTP 协议的好处是易于架设, 可以通过 HTTPS 提供只读的仓库,这意味着可以加密传输内容HTTP 协议的消极面在于,相对来说客户端效率更低。克隆或者下载仓库内容可能会花费更多时间,而且 HTTP 传输的体积和网络开销比其他任何一个协议都大。因为它没有按需供应的能力 — 传输过程中没有服务端的动态计算 — 因而 HTTP 协议经常会被称为傻瓜(dumb)协议

13.2. 生成 SSH 公钥

  • 大多数 Git 服务器都会选择使用 SSH 公钥来进行授权。系统中的每个用户都必须提供一个公钥用于授权,没有的话就要生成一个。
  • SSH 公钥默认储存在账户的主目录下的 ~/.ssh 目录
  • 假如没有这些文件,或者干脆连 .ssh 目录都没有,可以用 ssh-keygen 来创建。 然后把公钥给你或者 Git 服务器的管理员
  • git
leetcode-1
Make&&Valgrind
  1. 1. 1. 历史
    1. 1.1. 1.1. 区别
    2. 1.2. 1.2. 特点
  2. 2. 2. 状态
    1. 2.1. 2.1. 三个工作区域
  3. 3. 3. 初始配置
  4. 4. 4. 帮助信息
  5. 5. 5. 获取 Git 仓库
  6. 6. 6. 文件状态
    1. 6.1. 6.1. 种类
    2. 6.2. 6.2. 检查当前文件状态
    3. 6.3. 6.3. 暂存已修改文件
  7. 7. 7. 查看提交历史
  8. 8. 8. 撤消操作
    1. 8.1. 8.1. 覆盖提交信息
    2. 8.2. 8.2. 取消暂存的文件
    3. 8.3. 8.3. 撤消对文件的修改(检出)
  9. 9. 9. 多commit信息
  10. 10. 10. 远程仓库
    1. 10.1. 10.1. 查看远程仓库
    2. 10.2. 10.2. 添加远程仓库
    3. 10.3. 10.3. 从远程仓库中抓取与拉取
      1. 10.3.1. 10.3.1. 处理本地冲突
    4. 10.4. 10.4. 推送到远程仓库
    5. 10.5. 10.5. 远程仓库的移除与重命名
    6. 10.6. 10.6. 多个远程仓库
  11. 11. 11. 标签
    1. 11.1. 11.1. 列出标签
    2. 11.2. 11.2. 创建标签
    3. 11.3. 11.3. 共享标签
  12. 12. 12. Git 分支
    1. 12.1. 12.1. 对象
    2. 12.2. 12.2. 指针
    3. 12.3. 12.3. 分叉(diverged)
    4. 12.4. 12.4. 分支的新建
    5. 12.5. 12.5. 分支的删除
    6. 12.6. 12.6. 分支合并
      1. 12.6.1. 12.6.1. 遇到冲突时的分支合并
    7. 12.7. 12.7. 分支的管理
    8. 12.8. 12.8. 利用分支进行开发的工作流程
    9. 12.9. 12.9. 远程分支
    10. 12.10. 12.10. This branch cannot be rebased due to conflicts
  13. 13. 13. 协议
    1. 13.1. 13.1. 分类
    2. 13.2. 13.2. 生成 SSH 公钥
© 2024 何决云 载入天数...