git命令详解

2023-05-13  本文已影响0人  CDF_cc7d

Git基本概念

Git是什么

Git是一个分布式代码管理工具,而SVN则是集中式代码管理工具。

  1. 集中式: 所有的代码都保存在中央服务器,所以提交必须依赖网络,协同工作的人们都通过客户端连接到这台服务器,取出最新的文件或者提交更新
  2. 分布式: 每个终端都是一个仓库,客户端并不只提取最新版本的文件快照,而是把原始的代码仓库完整的镜像下来,每一次的提取操作,实际上都是一次对代码仓库的完整备份。因此可以在本地进行提交,并不需要依赖网络。
git.jpg

工作区域

  1. 工作区: 实际的工作目录
  2. 暂存区: 代码add以后暂时存储的区域
  3. 仓库区: 分为本地仓库和远程仓库。 本地仓库是commit以后存储的区域, 远程仓库是push以后存储的区域

commit节点

每次Git提交以后都会生成一个节点,每个节点都会有一个哈希值作为一个唯一标示,多次提交就会形成一个线性节点链, 如下图所示,C2是最后一个提交节点,那么C2会包含前面C1和C0的提交内容。右边则是每次提交对应的哈希值


commit节点.jpg

HEAD

HEAD相当于一个指针,它可以指向任意一个节点,它指向的那个节点就是当前工作节点。如上图所示,当HEAD指向C2,那么当前工作目录就是C2。

分支

分支可以让开发分多条主线同时进行,每条主线互不影响

假如将整个项目比作一个单机游戏,节点就是玩家保存的进度,HEAD指的就是玩家当前选择的那个进度,而分支可以认为是不同的玩家在玩这个游戏的历程。


Git命令详解

1. 初始化

1.1 初始化本地仓库

image.png

1.2 关联远程仓库

git remote add <自定义仓库名> + 仓库ssh地址
git init初始化仓库以后需要进行git remote操作,实现本地和远程仓库绑定,这样才算是完整创建本地仓库


10239771-c1264302673ac2d3.png

1.3 克隆远程仓库到本地

可以通过git clone的方式直接将远程仓库克隆到本地,此时远程仓库名默认为origin。


image.png

2. 查看文件状态

2.1 查看文件状态

git status


image.png

2.2 查看文件状态简览

git status -s
相对于git status来说显示的内容更简单直观一点

  1. 新添加的未跟踪的文件前面有??, 即test5.txt
  2. 新添加的文件已经放入暂存区的,文件前面会显示A, 即test4.txt
  3. 文件被修改但是没有放入暂存区,右边会出现M, 即 test2.txt和test3.txt
  4. 文件被修改并且已经被放入暂存区,左边会出现M, 即test.txt
  5. 文件被删除但是没有放入暂存区,右边会出现D
  6. 文件被删除并且已经被放入暂存区,左边会出现D
10239771-7f41019e0b09efa2.png

3. 查看修改

3.1 查看工作区所有文件的修改

git diff

diff --git a/git_test_demo/README.md b/git_test_demo/README.md
这一行显示diff下两个文件的对比。 a版本指的是修改前的README.md, b版本指的是修改后的README.md

deleted file mode 100644
删除了文件 100指的是普通文件,644代表文件权限
Index e69de29..000000
index后面的两个数字表示两个文件的hash值,因为是删除,所以后面的数字hash值为000000。

diff--git a/git_test_demo/test.txt b/git_test_demo/test.txt
这一行显示diff下两个文件的对比。 a版本指的是修改前的test.txt, b版本指的是修改后的text.txt

Index 5d58fcd..f316c8d 100644
index后面的两个数字表示两个文件的hash值(index区域的5d58fcd与工作区的f316c8d对象对比)

--- a/git_test_demo/test.txt
+++ b/git_test_demo/test.txt
---表示修改前, +++表示修改后

@@ -2,3 +2,4 @@
该行表示接下来下面显示的内容所在的位置。
-表示修改前, +表示修改后
-2,3 表示修改前test.txt文件从第2行显示,一直到第4行(2位起始行, 3位向后偏移的行数。即显示修改内容从第2行到第4行)
+2,4 表示修改后test.txt文件从第2行显示,一直到第5行(2位起始行, 3位向后偏移的行数。即显示修改内容>从第2行到第5行)

10239771-2fb3db1bfd16f303.png

3.2 查看暂存区所有文件的修改

git diff --staged


10239771-e3829ebce25792f9.png

3.3 查看两次提交之间的差异

git diff <commit id1> <commit id2>


10239771-d3bb8111379d0d9f.png

3.4 查看两个分支之间的差异

git diff <branch1> <branch2>


10239771-f11717788431e6c0.png

3.5 查看指定提交的修改内容

git show <commit id>


image.png

3.6 查看指定文件的修改历史

git blame <file>


10239771-e18d7f154f4a0990.png

3.7 查看最近N次提交的修改内容

git log -p -N


image.png

4. 查看提交记录

4.1 查看当前分支的历史提交记录

git log


image.png

4.2 简洁的方式查看提交历史

git log --pretty=oneline


10239771-6471d6d5cfb9872b.png

4.3 查看分支合并图

git log --graph


image.png

4.4 查看所有的操作记录

git reflog

任何的操作记录都会显示在reflog上面
显示内容为Commit id + 执行的命令 + 提交描述


10239771-6f72efa3f1cf3170.png

4.5 查看指定提交记录是在哪个分支提交的

git branch --contains <commit id>


image.png

5. 添加文件

10239771-47fb8043bfa02953.png
10239771-296f1c6468e5ab64.png
10239771-2a68331f954423c0.png

当前目录下修改了三个文件test.txt, test2.txt, test3.txt, 新增了test4.txt, 移除了README.md

5.1 暂存工作区所有的文件

git add . / git add -A / git add --all


10239771-7709bc2ea26a2cc5.png
10239771-45412a88dcf83b06.png

5.2 暂存工作区指定的文件

git add <file1> <file2>


10239771-bfb5f31b5ab50470.png

5.3 暂存工作区指定目录的所有文件

git add {directory}


10239771-b5ba850285aeee1b.png

5.4 暂存工作区所有文件,不包含删除的文件

git add *


10239771-5f9fab2344181bd5.png

5.5 暂存工作区所有文件,不包含新增的文件

git add -u


10239771-b46ab2da2fddeb3f.png

6. 分支

6.1 查看本地分支列表

git branch (带星号指的是当前的分支)


10239771-1d9bf08243752c0d.png

6.2 查看远程分支列表

git branch -r


10239771-4484d022e5ab5ca7.png

6.3 查看所有的分支列表(包括本地和远程)

git branch -a


10239771-2869df91a12d34ec.png

6.4 查看本地每个分支最后一次提交

git branch -v


10239771-e57a0587baa5397a.png

6.5 查看本地每个分支最后一次提交,并且与远程分支进行比较

git branch -vv


10239771-91b7c5de7de51b31.png

6.6 创建分支

git branch <branch>


10239771-52f3f1b4d155d705.png

6.7 删除指定分支

git branch -d <branch>


10239771-8ed4001b57a3b2c9.png

6.8 强制删除指定分支

git branch -D <branch>


10239771-07930ec52c2e9341.png

6.9 删除远端分支

git push origin --delete <branch>


10239771-4e2665df236cb6ce.png

6.10 切换到上一个分支

git checkout -


10239771-dc9bd14f83e3cd1e.png

6.11 切换分支

git checkout <branch>


10239771-38038617f5a15dbb.png

6.12 创建分支并且切换到该分支

git checkout -b <branch>

等价于git branch <branch> + git checkout <branch>

10239771-6683944eee31017d.png

7. 提交

7.1 提交暂存区的文件到本地仓库

git commit -m "message"


10239771-9aadfd910c9e3b3f.png

7.2 跳过暂存区直接执行提交

git commit -a -m "message" / git commit -am "message"
这种方式可以直接提交工作区修改后的文件,但是新添加的文件是不会提交的,仍然需要先add到暂存区。


10239771-21c9d92cfb9207a8.png 10239771-dca6e17ba4340ff6.png

7.3 修改之前已经提交的结果

git commit --amend

第二次提交将 代替 上一次提交的结果。适用于提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了的情况。

10239771-914a58b6dcef53c5.png

7.4 将本地提交推送至远端

git push origin <branch>


image.png

7.5 强制提交到远端

git push origin <branch> --force

以下图为例, 将上面那次commit给撤销以后,然后执行git push origin cdf2发现无法推到远端仓库。
所以执行了git push origin cdf2 --force强制将远端仓库的那次提交也给撤销掉

10239771-430dbd91d65bdcef.png

7.6 将修改提交到远端指定的分支

git push origin <commit id>:<branch>

以下图为例

  1. 在cdf2的分支下面提交了一个test4.txt文件
  2. 将test4.txt文件推到了远端cdf4的分支上
image.png

8. 拉取

8.1 拉取远端分支的最新代码

git fetch

git fetch --depth=N
只拉取最近N次的commit, 这样可以加快拉取速度。 但是由于只拉取最近N次的commit,所以相应的本地也只能看到最近的N次commit。

git fetch 会先将远端的代码拉取下来保存到FETCH_HEAD中,然后通过git merge的方式将FETCH_HEAD的代码merge到当前本地分支


10239771-67b64e0f2f53700f.png 10239771-e83db2b13ac931b6.png

8.2 拉取远端分支的最新代码, 并且合并到本地分支

git pull
git pull则是git fetch + git merge的操作, 直接更新本地分支的代码


image.png 10239771-b61f91ce03ec8f65.png 10239771-4e354cb8a01c9f3a.png

8.3 拉取远端分支的最新代码,并且合并到本地分支

git pull --rebase

当本地没有任何提交记录,那么git pull = git pull --rebase。

当本地提交了一个节点,远端同一个分支也更新了节点
通过git pull的方式会产生一个merge的提交记录
如右下图所示

10239771-19e3e3b7b0d539fa.png
image.png

通过git pull --rebase的方式,则会让整个提交记录看起来更线性。


image.png 10239771-983919b3c732a946.png

9. 回退

9.1 清空暂存区

git reset HEAD/ git reset --mixed


10239771-54270e4e2704301e.png 10239771-0cfd546d9e72949d.png

9.2 将HEAD回退N个节点

git reset HEAD~N

例如N=2,那么HEAD将往前推2个节点,会指向倒数第三个节点。 回退以后保留修改文件

image.png

9.3 重置所有文件到未修改的状态

git reset --hard


10239771-f3c5372d1f16df5a.png

9.4 将HEAD回退一个节点

git reset --hard HEAD^ / git reset --hard HEAD~1


image.png

9.5 将HEAD回退到指定的节点

git reset --hard <commit id>


image.png

9.6 撤销工作区指定文件的改动

git checkout -- <file> / git restore <file>


10239771-d87a5c1120702b32.png 10239771-8f90a1d808448176.png

9.7 将HEAD指向指定节点

git checkout <commit id>


image.png image.png

9.8 将HEAD指向前一个节点

git checkout HEAD^


image.png
10239771-f14c1a85694c95a5.png

9.9 将HEAD往前移动N个节点

git checkout HEAD~N

例如N=2,那么HEAD将往前推2个节点,会指向倒数第三个节点

image.png 10239771-01646bc292fa7d8e.png

9.10 还原指定节点的修改

git revert <commit id>

revert以后会将原来的修改回退掉,并且新增一条提交记录

10239771-3a20d7dacbf66618.png

9.11 还原上次的提交

git revert HEAD


image.png

10. 保存

10.1 保存当前修改的内容

git stash


10239771-5b84eb5c04f1584f.png

10.2 查看保存的记录列表

git stash list


10239771-02692bdba3350226.png

10.3 将上一次保存的内容恢复到工作区

git stash apply


10239771-f8c37eeceebb68d7.png 10239771-928f7f9a24afec73.png

10.4 删除stash里面上一次保存的记录

10239771-2a049696306a1935.png

10.5 上一次保存的内容恢复到工作区,并且删除对应的记录

git stash pop


10239771-fca4f47aee9d108d.png

10.6 清空stash里面所有保存的记录

git stash clear


10239771-9da539a36e866489.png

10.7 删除stash里面指定index的那一条记录

git stash drop <index>


10239771-6001e0112d23cb76.png

11. 标签

11.1 在指定节点上创建标签

git tag <tag name> <commit id>


10239771-afe7a60401aa45b0.png

11.2 查看所有标签

git tag


10239771-eef8ff3a3835b659.png

11.3 删除本地标签

git tag -d <tag name>


10239771-cd0d5e1e5e57a925.png

11.4 将本地指定标签推送到远端

git push origin <tag name>


image.png

11.5 将本地所有标签推送到远端

git push origin --tags


image.png

12. 合并

合并整体的链路比较复杂,并且在命令行中不好直观呈现,下一节做比较的时候再详细给出

12.1 将指定的提交节点复制到当前最新的节点上

git cherry-pick <commit id>
执行git cherry-pick <commitid>将其他分支的指定commit记录复制过来提交到当前分支


10239771-7a13ce6d267207a7.png

12.2 将指定分支的提交记录复制到当前分支

git merge <branch>

  1. 执行git merge cdf将cdf分支的代码合并过来
  2. 产生冲突以后,将文件冲突解决掉
  3. 执行git add .命令
  4. 执行git merge --continue。
  5. 然后就会产生一条merge的commit记录
10239771-2da69ab30c55b310.png
image.png

12.3 将指定分支的提交记录复制到当前分支,并且保持线性的提交记录

git rebase

  1. 执行git rebase cdf将cdf分支的代码合并过来
  2. 产生冲突以后,将文件冲突解决掉
  3. 执行git add .命令
  4. 执行git rebase --continue。
  5. rebase以后的提交记录更具线性
10239771-2dd4bfa2f26af960.png

git rebase之前的commit记录

image.png

git rebase 之后的commit记录

image.png

12.4 将多次的提交合并为一次提交

12.4.1 git rebase -i HEAD~N

将最近的N个commit合并为同一个commit。

12.4.1.1 执行前:
image.png
12.4.1.2 执行后:
image.png

12.4.2 git rebase -i <commit id1> <commit id2>

将<commitid1>到<commitid2>之间的提交合并成一个提交,左开右闭。所以如果要合并最近的三个提交,那么只需要<commitid1>填倒数第四个提交的commitid, <commitid2>填最近一个提交的commitid即可

12.4.2.1 执行前:
10239771-e0b98eb4eb55f320.png
12.4.2.2 执行后:
10239771-dc9137290cfd3eb6.png

Git相似命令比较

1. 「git reset HEAD^」 VS 「git checkout HEAD^」

1.1 git reset HEAD^

git reset HEAD^在当前分支将HEAD指向了前一个节点,这个时候可以直接执行push origin <branch> --force就可以更新远端分支


image.png

1.2 git checkout HEAD^

git checkout HEAD^则是脱离了当前分支,然后将HEAD指向了前一个节点。但是main分支最新的commit依然是C4, 这个时候执行push origin <branch> --force会提示Everything up-to-date。


image.png

2. 「git reset HEAD^」VS 「git revert HEAD」

2.1 git reset HEAD^

git reset HEAD^将本地分支最新的commit记录指向了前一个节点,最新的commit已经变成了C3,这个时候可以直接执行push origin <branch> --force就可以更新远端分支


image.png

2.2 git revert HEAD^

git revert HEAD则只是将上一次的提交的记录回滚,并且重新提交了一遍,虽然最后的结果跟reset一样,但是在分支上面会新增一个节点


image.png

3. 「git cherry-pick」 VS 「git merge」 VS 「git rebase」

3.1 git cherry-pick

下图HEAD指向了main, 我们想将cdf分支的C3复制到当前所在位置的话,就可以使用cherry-pick的方式


image.png

如图所示,将cdf分支上C3的提交cp到main分支变成了C3',C3'跟C3就只有提交的内容一样,属于不同的两次提交


image.png

3.2 git merge

下图HEAD 是指向了 main,我们想将 cdf 分支的代码合并到 main 分支上来,那么执行 git merge cdf


image.png

合并之后,多了一个C6节点,这个节点的父节点有两个,分别是C4和C5。 main和HEAD指向了合并后的新节点


image.png

3.3 git rebase

下图HEAD指向了main, 我们想将cdf 分支的代码合并到main分支,但是又想让提交的记录比较整洁,这个时候就可以使用git rebase的方式


image.png

rebase,顾名思义就是重新以XX为父节点。重新创建一个"分支",将需要rebase的分支提交节点给复制过来,然后再将当前分支的节点放到新"分支"最新的节点上。并且HEAD指向了新"分支"(注:这里的分支打个双引号是因为它其实并不是一个真正意义上的分支,它没有分支名,只有HEAD),而且原来分支节点依然还存在,如果还想用到之前的节点,可以通过checkout 对应的commit id即可


image.png

Q&A

1. 应该如何回退自己的git操作

1.1 发现自己提交的代码有点问题, 想要撤回上一次的提交,但是又想保留原先的修改,那么执行git reset --mixed或者git reset --soft 。 git reset默认就是mixed

1.2 发现自己的提交就是有问题的,想要撤回上一次的提交,并且不想保留原先的修改,那么可以执行git reset --hard

1.3 如果我们想要撤回远端分支的提交,但是远端分支又是一个protected的分支,那么我们只能选择git revert的方式将修改还原,但是会在分支上新增一次提交记录

2. 应该怎么保存自己的代码?

2.1 一个feature开发完成或者一个bug修改完成,这个时候需要切换分支去做其他事情,那么可以commit到本地仓库,然后推到远端自己建的分支上面。 但是后续如果有些修改但是又不想再增加commit了,那么可以通过git commit -amend的方式来覆盖上一次commit的记录

2.2 有时候工作区文件改了一半,但是又不想增加一个commit,但是需要把远端的最新代码拉下来又发现有冲突拉代码失败。 这个时候就可以先通过git add的方式放到暂存区,然后git stash将文件保存起来。

3. 如何快速查到一段代码的修改记录?

3.1 如果只是想看这段代码是什么时候提交的,可以通过git blame -L N, +M --<file>查看

其中N代表是从第N行开始, M代表一共要看M行代码, file就是对应的文件名


image.png

3.2 如果需要看到某一行代码的修改记录,那么可以通过git log -L N, +M:<file>查看

其中N代表是从第N行开始, M代表一共要看M行代码, file就是对应的文件名


10239771-1139b4292e43a37f.png

3.3 AndroidStudio自带的git功能也非常好用,选中一段代码,右键Git->Show History for Selection就可以查看所有的修改记录

image.png

4. 如何快速查找某个人的提交记录?

git log --author=<email>


image.png

5. 如何快速查找某个commit?

6. 如何知道自己的某个commit 都合入了哪些分支 以及哪些版本(tag)?

如果知道对应的commitid,那么通过git branch --contains <commitid>


image.png

如果并不知道commitid,那么需要先通过git log --all --grep <key>的方式找到对应的提交记录,然后通过git branch --contains <commitid>


image.png

7. git reset --hard之后代码丢了,怎么恢复

7.1 如果你的代码现在在工作区或者是暂存区,你不小心执行了git reset --hard命令,那么真的是神仙难救,所以如果工作区有代码,切忌不要执行git reset --hard方法

7.2 如果你的代码已经push到了远程仓库,你不小心执行了git reset --hard命令,那么只需要git pull就可以恢复。如下图所示

image.png
10239771-afbd94145f2d24ec.png
image.png

7.3 如果你的代码已经push到了远程仓库,你不小心执行了git reset --hard命令,并且还强制推送到了远端,那么可以执行下面的步骤,如下图所示

  1. 通过git reflog查看所有的操作记录
  2. 找到撤销之前的那条commit
  3. 通过git reset --hard <commitid>
  4. 通过git push origin <branch> 的方式恢复远端分支

通过git reflog查看所有的操作记录,找到撤销之前的那条commit


10239771-886d97ffbd9c603e.png

通过git reset --hard <commitid>,git push origin <branch> 的方式恢复远端分支


image.png

8. 新增的文件刚好命中了.gitignore的规则,怎么提交

image.png

当你新增的文件或者修改的文件刚好命中了gitignore的规则,那么你执行git add命令的时候会有上面这段提示。通过git add -f <file>的方式就可以添加到暂存区。


image.png

当然如果觉得gitignore的规则不合理,修改.gitignore文件即可

9. 一个文件里面有多个bug单对应的修改或者是有些修改是测试代码,该怎么提交指定的内容

9.1 通过git add -p <file>的方式筛选出要提交的代码,如下图所示。

  1. 在test10.txt文件中新增四行,然后保存。


    image.png
    image.png
  2. 执行git add -p test10.txt的命令


    image.png
  3. 这里有几个命令需要执行
    a. y: 同意这段修改放入暂存区
    b. n: 不同意这段修改放入暂存区
    c. q: 退出
    d. a: 同意这段修改和这个文件中所有的其他修改都放入暂存区
    e. d: 不同意这段修改以及这个文件中所有的其他修改放入暂存区
    f. e: 自定义选择放入暂存区
    g. ?: 打印帮助
  4. 选择e进入编辑页面
    a. 新增行,不想提交(但是变更仍然在工作区)。删除整行
    b. 删除行,不想提交。用空格符" "代替"-"字符。
    c. 变更行,不想提交。上面两个结合——对于"+"所在行整行删除,对于"-"所在行,用空格符" "代替"-"字符
image.png
  1. 删除「add new line 2」和「add new line3」然后保存。然后执行git commit将test10提交到本地仓库


    image.png
  2. 根据commitid查看修改记录


    image.png

9.2 使用sourcetree提交

执行命令行来提交指定的内容多少是有点不直观,并且不易上手,采用sourcetree的方式就非常直观,选中指定的提交的内容然后点击暂存行即可


image.png

10. git push origin <branch> --force以后,如何回退

git push origin <branch> --force以后,远端的分支节点已经发生了改变,但是本地分支依然是有以前的commit记录,所以先使用git reflog找到之前的操作记录,通过git reset -hard <commitid>的方式回退到当时的版本, 然后git push origin <branch>来更新远端分支

上一篇下一篇

猜你喜欢

热点阅读