【git】(一)在vscode上使用git进行版本控制(结合指令、含示例)

开源 0

vscode中的git插件将git操作从git指令简化到简单的图形界面操作,不用再去记忆git指令,操作简单直观了很多。第一次使用时,为了加深理解,我将一些基本操作和该操作底层使用的命令结合起来,并包含实例,方便学习,也希望能帮助到初学者。

0.配置

在完成git的下载和安装后,一定要设置用户名称和email地址。这是非常重要的,因为每次Git提交都会使用该用户信息。如果没有配置信息,在使用vscode调动git进行commit时会出现这样的弹窗:
56aee266811d40a28356bce0bd5c383e.png

基本配置: 任意文件夹下打开Git Bash,或者打开任意终端,使用以下指令设置用户信息:

git config --global user.name "name"git config --global user.email "xxx@xxx.cn"

查看配置信息:

git config --global user.namegit config --global user.email

1.获取本地仓库、查看状态

1.1 获取本地仓库

【vscode中的操作】
打开需要进行版本管理的项目文件夹(即将创建本地git仓库的地方),找到git插件(源代码管理),点击open repository,如果该文件夹下还没有本地仓库,则会初始化一个仓库;如果之前已经创建过仓库了,那么vscode会引导用户打开已有的仓库。
f9f9f82da2da4cf7afd0c4be15c0b52e.png
【对应的git指令】
以上的操作相当于:在该文件夹下,进入终端(可以是git bash、也可以是终端),输入以下git初始化指令。该命令用于在当前目录初始化一个新的 Git 仓库。如果当前目录已经是一个 Git 仓库,执行此命令不会有任何效果。

git init

【结果】该文件夹下有.git隐藏目录,且git插件部分显示了该目录下各文件的状态,说明本地仓库已经存在。
39b0e66ea51c4604890de91dd5faffa3.png

【示例】

作为示例,在该文件夹里创建test1、test2两个文件:
243146ac9f1849c19cf0ecf83c0d66a7.pngaafa28e6b22043e7a79998f6139e8e57.png

1.2 查看状态

文件状态表明了各文件是否被 Git 识别和纳入版本控制。在vscode中的Git插件,文件可以处于以下几种状态:

  • 未跟踪(U):文件不存在于最近的提交中,Git 尚未开始跟踪这个文件。当在仓库中创建新文件时,它们最初都是未跟踪的。
  • 已修改(M):文件自上次提交以来已经被修改,但还没有被暂存。
  • 已删除(D):文件在本地仓库中存在,但是在工作区中被删除,该删除操作还没被暂存。
  • 已暂存(索引):文件的当前版本已经被标记为将在下次提交时被包含,vscode中包含以下暂存的三种状态:
    • 已添加索引(A):文件已经被添加到暂存区
    • ​​​​已修改索引(M):文件自上次提交以来已经被修改,且已经被暂存。虽然显示的也是M,但是需要和“已修改”分别开。
    • 已删除索引(D):文件在本地仓库中存在,且删除操作被暂存。虽然显示的也是D,但是需要和“已删除”分别开。

 【vscode中的操作(其实不用操作)】
Git插件的图形化界面本身可以轻松观察到当前全部文件状态,十分方便。此时Git 插件会显示以上test1、test2文件的状态为“未跟踪”(后面的大U),因为它们尚未被纳入版本控制。80b2672727c043e8a47c7cfe3e706f06.png

【对应git指令】

git status

如果使用该指令,可以查看所有文件的状态:
36187e58a49b412aab031f0ee3d9cdca.png

2.工作区与暂存区之间的转换

2.1 工作区->暂存区

【vscode中的操作】
在git插件中,“更改”部分列出了所有未暂存(包括“未跟踪”、“已修改”、“已删除”状态)的文件。
点击“更改”后面的按钮可以对全部文件进行操作;也可以鼠标悬停到某一个文件,对单一文件进行操作:曲线剪头是撤销所有修改(这个在后面提及)," + " 号是暂存所有修改
aef7807c84014fad87c776232e8ee4b5.png

【对应的git指令】

添加全部未暂存文件到暂存区:将当前目录下所有新的或修改过的文件添加到暂存区。

git add .

添加单一未暂存文件到暂存区:将 <file> 替换为要暂存的文件名(例如,test1.txt)。

git add <file>

【结果】文件从“更改”栏进入“暂存的更改” ,文件状态变成“已暂存”(后面的大A)
8581c1bec36e49e0b57bd9c222f4a252.png

2.2 暂存区->工作区

从暂存区中移除特定的文件,回到工作区状态,且不修改该文件工作区的内容

【vscode中的操作】
在Git插件中,“暂存的更改”部分列出了所有已经暂存的文件。
同理,点击“暂存的更改”后面的按钮可以对全部文件进行操作;也可以鼠标悬停到某一个文件,对单一文件进行操作:上图所框选出的“-”号是移除暂存文件

【对应的git指令】

将暂存区中的所有文件取消暂存

git reset HEAD -- .

取消暂存某个特定的文件:将 <file> 替换为要暂存的文件名(例如,test1.txt)。

git reset HEAD -- <file>

【结果】文件从“暂存的更改”栏移除。出现在“更改”栏,文件状态变回未暂存状态。

2.3 暂存区与工作区同一文件版本不同的情况(冲突问题)

在 VSCode 的 Git 插件中,“暂存的更改”部分显示的不仅仅是 Git 暂存区中的文件,它还可能包括那些已经被暂存但之后又被修改的文件“暂存的更改” ≠ “暂存区”,在 Git 命令行中,只有真正被暂存且未被进一步修改的文件才被视为暂存区的一部分。

  • 只在“暂存的更改”部分出现的文件:文件状态为“已暂存”(包含“已修改索引”、“已添加索引、“已修改索引”),这些文件的当前版本已经被添加到 Git 的暂存区,准备在下一次提交中被包含。

  • 同时在“暂存的更改”和“更改”两个部分出现的文件:状态不是“已xx索引”,这些文件之前可能已经被暂存,但在工作区中又有了新的修改。这些修改尚未被添加到暂存区。

【示例】

①暂存test1.txt:此时该文件状态为“已添加索引”(A),表示文件的当前版本已经存在于 Git 的暂存区中。
21710baeebb949ada8dc9ad306d5af54.png
②修改test1.txt:将所有的“广东”改成“东莞”。同时观察文件状态——此时test1文件状态为“已修改”,同时也在“更改”区域出现。
3bc03c53ace0467d885c5e9111259e6a.png2563c5449b9b46bfac0784678b811e35.png
此时,由于对文件做了新的修改,它的状态变为“已修改”(M),并且也出现在 VSCode 的“更改”区域。尽管这个修改后的状态为“M”的test1.txt仍然显示在“暂存的更改”部分,它实际上表示工作区中的文件版本与暂存区的版本不同。这些更改尚未被添加到 Git 的暂存区。

③此时可进行的操作:

(1)重新暂存修改:按照上述 工作区->暂存区 的方法,将工作区中的新修改添加到暂存区,即再次执行add。这样,test1.txt文件状态由M变为A,vscode中“暂存的更改”被覆盖,即全部“广东”变为“东莞”,保留了“更改”中的新内容:
7275940456bc42bd9f01063fedf155ca.png
(2)撤销旧版本文件的暂存状态:即不提交这些新的修改,而是想要撤销对旧版本test1.txt的暂存状态,即可按照上述 暂存区->工作区 的方法,将旧版本的该文件从暂存区中移除,同时工作区中的新修改仍然保留(即“东莞”版本)。
80b2672727c043e8a47c7cfe3e706f06.png

 【有可能出现的问题】

在使用“-”操作时,如果跳出以下弹窗,这是因为“暂存的更改”和“更改”中的test1.txt内容存在冲突,它不知道你需要保留哪个版本的文件放入工作区
(好像在没有提交的时候会出现这个情况,如果已有提交,似乎就不会再有这个弹窗,而是直接移除暂存版本)

e60b52ecb7664857ba93ed284c3ce67d.png

(3)手动融合两个版本,并暂存融合版本:点击更改区的该文件,vscode会显示出暂存版本(左侧)和当前工作区版本(右侧)的内容,并高亮差异部分。暂存版本不可更改,只能对照,可以直接在工作区版本手动更改融合,也可以使用中间的按钮来对各行的差异部分做取舍:箭头是保留暂存版本方案,+号是采用工作区版本方案
97d77fbe57584224896105ceeff9a071.png完成融合后,按照上述 工作区->暂存区 的方法,将工作区中的新修改添加到暂存区。

3.提交、修改与回退

3.1 提交、查看提交历史

再次提示:已暂存状态为“已修改索引”、“已添加索引”、“已删除索引”(“索引”就是暂存),未暂存状态为“已修改”“未追踪”“已删除”

【vscode中的操作】
在输入框中输入本次提交的注释,描述代码的版本或者内容修改的情况,方便之后进行浏览差异。输入之后点击提交,会将所有暂存区的文件进行提交。fc98cacb05ea4552a0dce79cf59adb6a.png

提交后,在“源代码管理图”中,可以看到提交历史,鼠标悬浮在上面可以获取更多信息,点进去也可以看该版本的具体代码与前一版本的差异。
3baf795161534269b91bfdd8f44eb5c1.png

【对应的git指令】
将暂存区的文件提交到本地仓库的当前分支,将“Your commit message”替换为提交注释。

git commit -m "Your commit message"

查看提交历史(通过日志):

git log

3.2 修改已提交的文件

一旦文件被提交,并且之后没有发生更改,它不会在 Git 插件的“更改”或“暂存的更改”部分显示。这是因为该文件的状态与仓库中的最新提交相匹配,没有新的更改需要跟踪。
如果在提交后又对文件进行了修改,那么这个文件将出现在 Git 插件的“更改”部分,并标记为“已修改”,因为现在它的状态与仓库的最新提交不再一致。
对于进行了修改的文件,可以再次进行上文所述 暂存区<—>工作区 的转换,放在暂存区的全部文件用于等待下一次提交。

【示例】

test1.txt文件在提交“初版0.1”后没有被修改,此时的文件状态如下:它不会在 Git 插件的“更改”部分显示,因为它的状态与最后一次提交的版本一致。
a4643c44ad05498f8b53ed454b9063ad.png
此时,Git插件只显示了未追踪的test2.txt文件,test1.txt文件虽然没有显示,但仍然存在于仓库中,只是没有新的更改需要版本控制。

①对test1.txt文件进行修改,删掉其中几行,并将版本改成0.2
ffe8839dd30e491382ef75ef68d41396.png
②查看Git插件,修改后的test1.txt文件(工作区版本)出现在了“更新”部分,文件状态为“已修改”,点击后可以看到工作区版本的文件内容(右)与最新提交版本的文件内容(左)的差异d57cad6dfa00406eaad83dafdc1b249a.png
③ 使用add暂存test1.txt,该文件进入“暂存的更改”栏,文件状态为“已修改索引”【暂存状态】,点击后可以看到暂存版本的文件内容(右)与最新提交版本的文件内容(左)的差异
d7bfe4714ad641618524aa44d3badb3b.png

④再次修改test1.txt:将所有的“厦门”改成“福州”。此时test1文件状态为“已修改”,同时也在“更改”区域出现。点击后可以看到工作区版本的文件内容(右)与暂存版本的文件内容(左)的差异。
0537cae765ee4d9f9fb9f34b25ac47aa.png141762094bb2492990fcc66e5c900c98.png

⑤再次使用add暂存test1.txt,该文件进入“暂存的更改”栏,文件状态为“已修改索引”【暂存状态】,点击后可以看到暂存版本的文件内容(右)与最新提交版本的文件内容(左)的差异。5e12b1339a704f679e78ff9bc94a3ed0.png

3.3 撤销全部修改

撤销全部修改针对当前的未暂存文件,即“更改”中的文件,分为两种操作,都需要舍弃当前的工作区版本,一是回退到暂存版本;一是回退到最新提交版本。

【vscode中的操作】
在vscode中,这两种操作没有显式的区分,实现的方法就是点击“更改”栏的文件后面的“曲线箭头”。具体回退的版本为点击该文件时,编辑区左边显示的内容。即,如果暂存区有该文件的历史版本,就会显示暂存版本;如果暂存区没有该文件的历史版本,就会显示最新提交版本。
(一个题外话:“暂存的更改”栏下的文件,永远都会显示 最新提交版本 和 暂存版本)
9612ddbc82634812af8dc7e173c8fbfb.png

结合以上示例,在第②步时,暂存区为空,因此显示工作区版本和最新提交版本;第④步时,暂存区已经有一个该文件的历史版本,因此显示工作区版本和暂存版本。

如果在第④步后,点击了test1.txt后面的“曲线箭头”,该工作区版本就会回退到暂存版本(缺行 + “厦门”),同时,因为暂存版本和回退后的工作区版本内容一致,该文件将只挂载在“暂存的更新”栏,且状态将为“已修改索引”。
假如:暂存区有历史版本,工作区在暂存版本的基础上做了修改,此时需要回退到最新提交版本,可以这么操作:根据上述2.2移除暂存区文件,使暂存区为空,点击撤销箭头,回退到最新提交版本。

【对应的git指令】

将工作区中的文件替换为暂存区或最新提交的版本。将 <file> 替换为要暂存的文件名(例如,test1.txt),或者. (全部文件)

git checkout -- <file>

3.4 版本回退与撤销

版本回退分为两类:一是直接回退到某版本并撤销该版本之后全部历史(reset);一是撤销某些版本的更改且保留历史(revert)。暂时没有在我的vscode中找到回退的图形化操作,只能copy到版本号,因此得结合git指令操作。

【操作】
在源代码管理图中选中要回退的版本,右键,选择复制commit ID。
1872d224fdfc424c8655c9da44ec86f3.png
打开终端,根据需求输入恰当的回退命令(reset/revert),将<commitID>替换为复制的版本号

3.4.1 回退 git reset:

git reset将 HEAD(当前分支的指向)回退到项目历史的某个特定点。有三种模式,分别是硬回退、软回退、混合回退。使用git reset命令会彻底撤销指定版本之后的所有提交,如果在和他人协作,或是正在操作主分支,要慎重使用。

①硬回退:将 HEAD、暂存区和工作区都回退到指定的提交版本(<commitID>)。所有在该提交版本之后的更改都会被永久丢弃。
适用场景:需要彻底回退到某个版本,并且不需要保留之后的更改。

git reset --hard <commitID>

②软回退:将 HEAD回退到指定的提交版本,但保留暂存区和工作区的状态不变。其他更改的内容会保留在暂存区,可以再次提交。
适用场景:想要撤销提交,但仍然需要对这些更改进行评估或重新组织后再提交。

git reset --soft <commitID>

③混合回退:将 HEAD 回退到指定的提交版本,清空暂存区,但不会改变工作区。更改的内容全部保留在工作区中,可以对工作区中的文件进行审查和修改,然后重新提交。
效果和软回退差不多,但是无法保留暂存版本。

git reset --mixed <commitID>

因为 --mixed 是默认选项,所以可以省略,简写成以下

git reset <commitID>

 【示例】

再次提交0.2版本,提交的文件为:缺行+“厦门”改“福州” 的test1-0.2 ,和提交0.1版本时没有提交的test2-0.1。
566535d35c4e4d33a879082f2e5285c7.png
从源代码管理图中也可以查看不同提交版本之间的差异。
f93ab2b4d62144b4aad7c5e24234bc96.png

 ①修改test2.txt文件,将其中一行改成首字母缩写,改成0.2版本,暂存。
4c68f1a7d02a423182ea27177c3cfb5b.png

再删除缩写下面的全部数字,这时文件在“暂存的更改”和“更改”中同时出现,文件状态为“已修改” 

67ba4553c85d4f2d856b8f2f6fac0acd.png ②在源代码管理图中复制“初版0.1”的版本号,进入终端,查看不同回退方式的效果:

(1)混合回退:git reset <commitID>
0ae27169b7724f3490bd1780368e153a.png
观察仓库状态:暂存区无文件,test1和test2的工作区版本没变,所有更改都保留在了工作区,最新提交版本回到初版0.1状态。test1状态为“已修改”,test2状态为“未追踪”(因为初版0.1没有提交teset2文件)
9fec649804ff49a49187b8f97ec6a1db.pngd28a31ad9cc24cd69f46f86700c2a06c.png

(2)硬回退:git reset --hard  <commitID>
a126000e59fb42f69e77ac115b005bd1.png观察仓库状态:Git 插件的“更改”或“暂存的更改”部分无文件,因为文件状态与仓库中的最新提交相匹配,没有新的更改需要跟踪。即,所有在提交该版本之后的更改,全部被丢弃。
接着查看文件目录:很糟糕,因为初始版本没有提交test2文件,test2被完全丢弃了,只剩下了初始提交版本内容的test1文件。【所以要谨慎】
84a7107345554c5f873d1a35acd45a91.png 2c4d89e9b0184e4db6a160e54793272b.png

(3)软回退:git reset --soft  <commitID> 
3773e4e684bf47569204c174f874bfae.png观察仓库状态:test2文件的暂存区版本、工作区版本没变,同时暂存区多了一个test1文件的历史提交版本,最新提交版本回到初版0.1状态。test1状态为“已修改索引”,test2状态仍为“已修改”。
cade38e971d74d12a92885f0ffda8d1d.pngb88c4253ebb64c7cbcf3f923bb15e19f.png7742ab2f29634407b788b776bb32adb6.png

3.4.3 撤销 revert:

revert用来撤销某个具体提交的更改。<commitID>理应为要撤销的版本,而不是要回退到的版本。它通过创建一个新的提交来实现,这个新提交的更改会抵消<commitID>的更改。它不会改变提交的历史,而是在历史的基础上添加一个新的提交。因此更加具有安全性。
适用场景:需要撤销历史中某次提交的情况,该提交可以穿插在历史中任意地方
这项操作通常在已经提交了当前版本的更改之后执行,要确保工作区是干净的,即当文件状态与仓库中的最新提交相匹配时。

git revert <commitID>

 【示例】

在使用revent时,要保证工作区是干净的,因此将对test2的修改进行提交,注释为 初版0.2(test2-0.2版本)。701799dddc35456889e7ccb52bf0af7e.png如果要撤销掉  初版0.2(test2-0.2版本) ,对应的要撤销的操作就是 修改test2文件(0.1->0.2)。即test2变回0.1版本。
复制 初版0.2(test2-0.2版本) 的版本号,输入revert命令进行版本撤销:
e6e1605e30d542c6a6ebd8b032bcac8e.pngcf00a625c06847be9315c292c741a3cf.png
此时,如果没有冲突,会自动定义revert注释,并将当前版本(左)和git进行反操作之后的版本(右)显示出来,此时test2在上一次提交进行的更改已经被抵消,并被放入暂存区,等待下一次提交。
【可以理解为:git试图根据撤销版本的操作进行反操作,来抵消撤销版本的更改,更改后进行暂存,然后展现在我们面前,如果我们认为它操作的正确,那么可以直接提交,如果代码比较复杂,我们认为它没有处理好,那么可以将其转换到工作区,在工作区继续修改,而后暂存提交】
提交revert进行的撤销操作,test2文件又回到了0.1状态
0131bba43ed742a293f3f37407d8b034.png

也许您对下面的内容还感兴趣: