版本管理工具Git:入门教程

Git使用教程

1.简介#

Git(读音为/gɪt/)是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。 也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。

分布式相比于集中式的最大区别在于开发者可以提交到本地,每个开发者通过克隆(git clone),在本地机器上拷贝一个完整的Git仓库。

2.安装与配置#

安装#

在Windows上使用Git,可以直接从Git镜像下载安装程序。

从npmmirror下载Git

打开安装程序,按默认选项安装即可。安装完成后,可以在开始菜单中中找到Git BashGit GUI Git CMD这几个软件,能打开说明安装成功;或者在命令行工具(例如PowerShell、cmd),输入命令git,能打印出Git的使用帮助,说明安装成功。

image-20221026160954423

配置#

安装完成后,为区别不同用户的提交记录,需要配置一下用户名和用户邮箱。使用命令行工具,输入命令并按下回车即可:

git config --global user.name "Your Name"
git config --global user.email "email@example.com"

使用如下命令可以查看当前全局配置的用户名和邮箱:

git config --global user.name
git config --global user.email

如果去掉--global,只在当前仓库生效。

3.Git的区域概念#

一个仓库拥有三个区,不同区拥有不同的功能。文件的提交流程是工作区->暂存区->版本库

工作区:就是工作目录。别名:工作树

暂存区:是 .git 目录下一个叫做 index 的文件,所以暂存区有时也被叫作索引(index)。暂存区是一个介于工作区和版本库的中间状态,通过 add 指令暂存的内容,都会被写进这个文件里,当执行提交时实际上是将暂存区的内容提交到版本库中。

版本库:就是本地仓库,它就是 .git这个文件夹。

三个区的说明

4. 从远程创建一个新仓库#

①创建一个远程仓库#

  1. 访问使用gitea自搭建的远程仓库(也可以使用Github、Gitee等第三方Git托管服务,功能基本上都是一样的)

  2. 注册或者登录账号(注意:邮箱要和本地配置的邮箱相同)

  3. 点击右上角+号,创建一个远程仓库

  4. 进入仓库信息填写页面:1为仓库的名称,这个仓库名会被 Git 设置为你的仓库的根目录的名称;2为仓库的描述,远程仓库会根据描述信息生成一个README.md文件;3为选择一个.gitignore模板,用于设置不允许git跟踪的文件。然后点击最下方的创建仓库来完成创建远程仓库

    mergeImg1

    刚创建完的仓库大概的样子:

    刚建完仓库的样子

    点击复制右边的仓库地址(也可以点击下载按钮,直接把仓库压缩包下载到本地)

②把远程仓库取到本地#

接下来就可以把远程仓库取下来了。取的方式很简单:在 powershell 或 cmd 中切换到你希望放置项目的目录中,然后输入:

git clone 远程仓库地址

Git就会把远程仓库clone到本地。(第一次下载和推送之前,Git可能会要求输入远程仓库的账户名与密码。)下载完成之后,我们会看到,当前所在的目录下出现了一个子目录,它的名字与远程仓库的名字相同:

可以看到在.gitignoreREADME.md这两个文件之外,还有一个.git的隐藏文件夹。

这个 .git 文件夹,就是你的本地仓库(Local Repository),你的所有版本信息都会存在这里。而 .git 所在的这个根目录,称为 Git 的工作目录(Working Directory),它保存了你当前从仓库中签出(checkout)的内容。现在把命令行工具切换到git-manual目录下,输入:

git log

可以看到仓库的提交历史:

image-20221114174229866

这时候只有一条提交历史,这个提交是远程仓库帮你做的,它的内容是创建你的初始 .gitignoreREADME.md 这两个文件。图中第一行中的 commit 右边的那一大串字符( ad30e8731......6175),是这个 commit 的 SHA-1 校验和(你可以暂时把它简单理解为这个 commit 的 ID,因为SHA-1是一种哈希算法,所以也叫它哈希值);后面括号里的内容(HEAD -> main ...)后续再说;第一行的下面,依次是这个 commit 的作者、提交日期和提交信息,其中提交信息记录了这个提交做了什么,是提交者填写的(当然,这条提交信息是 远程仓库 帮你写的)。

③尝试自己写个提交#

把远程仓库取到本地之后,我们就可以开始写代码了。为了练手,我们可以随便创建一个文本文件,.c,.txt等格式都可以,这里新建一个text.txt文件,向里面添加一段文本。

image-20221121143817259

Git的提交命令是commit,但是现在我们还不能直接提交,首先在命令行输入:

git status

status用来查看工作目录当前的状态

image-20221121144333394

这段文字表达的信息:

1.你当前在main分支

2.你的分支没有落后于origin/master

3.你有未追踪的文件,文件名是text.txt,如果你需要提交它,使用git add开始追踪文件。

由第三条可以看出,当前Git仓库对text.txt没有进行任何记录,对于Git仓库而言,text.txt是不存在的。所以,要想提交这个文件,需要先使用git add 让Git开始跟踪它的变化:

git add text.txt

执行完命令之后,git不会反馈成功的信息,这时候可以再次执行git status

image-20221121145712782

可以看到,信息已经变化了,text.txt字体变成了绿色,前面多了new file:的标记,这些都说明一点:shopping list.txt 这个文件的状态从 "untracked"(未跟踪)变成了 "staged"(已暂存),意思是这个文件中被改动的部分(第一次添加就是这一整个文件)被记录进了 staging area(暂存区)。

现在文件已经进入了暂存区,就可以提交了。提交的方式是用commit指令:

git commit -m "添加text.txt,并添加一些文字"

这样就完成了一次提交,-m "添加text.txt,并添加一些文字"是为这次提交附加的提交信息,一般用于说明本次提交所作的改动。

这时我们可以再次执行log指令,可以看到提交历史多了一条我们刚才提交的记录:

image-20221121151240368

④再来个提交#

我们这时再向text.txt添加一段文本,然后再次使用git status指令:

image-20221121151711570

image-20221121152109839

上面这段文本表达的信息:

1.当前在main分支

2.你的分支比远程的origin/main领先一个commit

3.text.txt被修改了,但修改还没有被暂存。使用git add <file>把工作区中的修改更新到暂存区;使用git restore <flie>放弃工作区中的修改。

Git的提示已经很清楚了,我们只需要再次使用git addgit commit,就完成了第二次提交。再次使用git log查看提交历史:

image-20221121154009478

我们可以看到最上面的总是最新的提交,这是Git默认的设置。

如果窗口区域不足以输出全部信息,Git会等待用户的操作:

image-20221121154310784

此时按下Enter,Git会输出下一行;按下Q,会退出Git。

⑤把提交推送到远程仓库#

到目前为止,我们已经在本地写了两条提交,我们想把它们推送到远程仓库,只需要使用push命令。在此之前我们先查看一下status

git status

image-20221121154852303

可以看到,当前分支已经领先远程分支origin/main两个提交了。

origin/main 的中的 origin 是远端仓库的名称,是你在用 clone 指令初始化本地仓库时 Git 自动帮你起的默认名称;mainorigin 上的分支名称。

而这句话的下面也说明了,你可以使用 git push 来把你的本地提交发布(即推送到远程仓库)。所以很简单,照做吧:

git push

第一次提交,可能需要使用输入账户密码进行认证:

image-20221121175220665

输入账户密码之后,我们观察命令行,这时候Git就把本地的提交到远程仓库了。

5.本地创建仓库并关联到远程仓库#

把本地仓库管理到远程仓库,有两种情况:要么本地已有仓库,要么本地还没有仓库。如果本地还没有创建仓库,则从①开始,如果本地已有一个仓库,直接从②开始:

①在项目目录中新建一个仓库#

  1. 只在需要创建仓库的项目目录,使用命令git init即可创建一个新的仓库

  2. git默认的分支名为master

  3. 然后在目录中添加一个.gitignore文件,在前面介绍过,它相当于忽略名单,用于设置不允许git跟踪的文件,避免一些不需要的文件被加入仓库。示例如下:

    image-20221121171156137

  4. 最好再添加一个readme.mdreadme.txt文件,用于介绍这个仓库。.md是一种轻量化的格式文件,全称markdown。

  5. 使用git addgit commit提交代码到本地仓库。只有产生一次提交之后,才能进行后续的操作

②创建一个空白的远程仓库#

  1. 这次使用Gitee做演示,访问远程仓库Gitee.com。(Github也可以,不过Github是国外网站,访问速度较慢)

  2. 注册或者登录账号

  3. 点击仓库列表右边+号,创建一个远程仓库

    image-20221121164418001

  4. 进入仓库配置页面,只需要设置仓库的名称即可

    image-20221121165054405

  5. 创建完成之后,我们可以看到仓库是一个完全空白的仓库,里面只有一些Gitee的提示。

    image-20221121165139726

③关联远程仓库#

上面创建的空白的远程仓库已经提示我们应该怎么操作了,我们照做即可:

git remote add origin https://gitee.com/sq800/new-repo.git

origin是远程仓库的别名,代表后面的链接指向远程仓库,也可以设置为其他字符串。

例如,示例使用的是Gitee,我们也可以把别名设置为gitee

git remote add gitee https://gitee.com/sq800/new-repo.git

④把本地提交推送到远程仓库#

git push -u origin master

这里-u可以不加,加上-u,下次再推送到这个分支,可以简化为git push

不出意外的话,我们本地的仓库就提交到远程仓库了。

6.HEAD、master、分支的本质#

我们使用git log看一下commit(提交)历史:

image-20221122184331793

我们以这两个提交举例说明。每一个commit后面的的一长串字符串是它的哈希值,前面4.②中我们已经介绍过了,哈希值是指向这个提交唯一的方式。

后面的(HEAD -> master, main),是两个指向这个commit引用。下面红色的(gitea/main),是远程仓库gitea(别名)的main分支指向的提交。

这说明当前本地仓库已经领先了远程仓库gitea一个提交。

HEAD:当前commit的引用#

HEAD是引用中最特殊的一个,它指向当前commit的引用,所谓当前 commit这个概念很简单,它指的就是当前工作目录所对应的 commit。上图中当前的commit就是最新的那个commit,每次当有新的 commit 的时候,HEAD 会转而指向最新的 commit

事实上,当使用 checkoutreset 等指令手动指定改变当前 commit 的时候,HEAD 也会一起跟过去。

总之,当前 commit 在哪里,HEAD 就在哪里,这是一个永远自动指向当前 commit 的引用,所以你永远可以用 HEAD 来操作当前 commit

分支(branch)#

分支也是一个引用,它也指向一个commit

HEAD除了可以指向某个提交,也可以指向一个分支,当它指向某个 branch 的时候,会通过这个 branch 来间接地指向某个 commit;另外,当 HEAD 在提交时自动向前移动的时候,它会带着它所指向的 branch 一起移动。

例如上面那张图,HEAD -> master中的master就是一个分支的名字,而它左边的箭头表示HEAD正在指向它,如果这个时候再提交一次,HEAD和master会一块向前移动。我们可以来验证一下:

image-20221122194518164

这里我省略了修改文件、addcommit的步骤。可以看到,经过一次新的提交后,HEAD以及它指向的master分支,都转而指向了新的的提交,而main分支依然指向原来的commit上,gitea/main 分支也依然指向原来的commit上。

master:默认分支#

上面的这个 master ,其实是一个特殊的 branch:它是 Git 的默认 branch(俗称主 branch / 主分支)。

所谓的「默认 branch」,主要有两个特点:

  1. 新创建的仓库是没有任何 commit 的。但在它创建第一个 commit 时,会把 master 指向它,并把 HEAD 指向 master
  2. 当有人使用 git clone 时,除了从远程仓库把 .git 这个仓库目录下载到工作目录中,还会 checkout (签出) mastercheckout 的意思就是把某个 commit 作为当前 commit,把 HEAD 移动过去,并把工作目录的文件内容替换成这个 commit 所对应的内容)。

注意:一些远程仓库由于某些原因,在上面创建仓库的时候,会把主分支设置为main。

branch 的通俗化理解#

尽管在 Git 中,branch 只是一个指向 commit 的引用,但它有一个更通俗的理解:你还可以把一个 branch 理解为从初始 commitbranch 所指向的 commit 之间的所有 commit 的一个「串」。例如下面这张图:

learn-git-branching

c0是初始提交,main分支指向c4提交,dev分支指向c3提交

7.创建、切换、合并、删除分支#

列出所有分支#

git branch

image-20221122203151806

*号代表当前所在的分支

创建分支#

在当前分支基础之上创建分支,新分支拥有当前分支的提交历史

git branch [分支名字]

创建一个新分支并切换到新分支

git ckeckout -b [分支名字]

切换分支#

git switch [分支名字]git checkout [分支名字]

合并分支#

合并指定分支到当前分支

git merge [分支名]

合并分支会产生一个新提交,HEAD会带着当前分支一起指向新的提交。而被合并的分支依然指向原来的提交。

合并冲突可以参考下一节的合并冲突来解决。

删除分支#

删除本地的分支

git branch -d [分支名字]

删除远程仓库的分支

#删除远程仓库gitea的某个分支,注意,默认分支不可删除
git push gitea -d [分支名字]

8.仓库的同步#

本地的仓库的提交和远程的仓库的提交要保持一致,需要手动同步,包含拉取和推送。

如果仅仅是一个远程仓库和一个本地仓库,并且只在本地仓库做修改并推送到远程仓库,那么并只需要使用push向远程仓库推送就可以了。

推送#

使用push把本地仓库的提交推送到远程仓库,前面已经介绍过。代码如下:

#把本地main分支推送到origin的main分支
git push origin main
#把本地main分支推送到origin的dev分支
git push origin main:dev

如果有多个同事共同开发一个项目,他们都向一个远程仓库提交代码。也就是说,不止一个本地仓库关联了远程仓库并推送提交;

或者只有一个人开发项目,但是在远程仓库上直接修改并提交了代码(这里仅用文本做示意):

新建项目

总之,此时远程仓库包含了本地没有的commit,因此直接push本地仓库上去会报错:

git push origin main

image-20221122152125642

拉取#

我们需要先使用pull拉取变化。pull会把远程仓库的commit拉取到本地,并与本地的仓库进行合并,它实际包含fetchmerge两条命令。

#拉取origin上的main分支合并到本地的main分支
git pull origin main
#拉取origin上的main分支合并到本地的dev分支
git pull origin main:dev

image-20221122152508715

使用git log,可以看到,远程仓库的commit已经被合并到本地仓库了,本地仓库已经完成了与远程仓库的同步:

image-20221122154659441

合并冲突#

团队开发时,我们一定会遇到一种情况:当同事A向远程仓库push时,同事B已经向远程仓库push了提交。这时同事A再向远程仓库push时,Git会报错误,错误截图就不放了,和上面的push报错是一样的。

这时候我们需要先把远程仓库的提交pull到本地:

#gitea是远程仓库别名,如果名字配的是origin,使用origin即可
git pull gitea main

Git会尝试自动合并冲突,如果冲突无法自动合并,Git会把冲突标记出来,留给我们自行合并。在Vscode中合并冲突如下图所示:image-20221122161313993

可以看到,text.txt文件产生了冲突:同事A添加的文本“同事A第一次提交”与同事B添加的文本冲突了。绿色块是本地的提交,蓝色块是从远程仓库拉下来的提交,他们之间用多个连续的等号隔开。

色块是VScode对Git的图形化支持。如果用记事本打开这个文件,我们可以看到它原本的样子:

image-20221122162121513

我们可以手动地删除不想要的代码,然后删除掉下图中红框框起来的部分,就完成了合并冲突的第一步。

image-20221122162731470

合并冲突的第二步就是提交修改后的第一步的代码:

# 首先把修改好的冲突文件添加到暂存区
git add .
git commit -m "合并远程冲突:...."

这样就完成了冲突的合并,然后就可以push到远程仓库了

git push gitea main

这时候我们看远程仓库,已经成功推送上去了:

image-20221122164754441

多人合作的基本工作模型#

  • 写完所有的 commit 后,不用考虑远程仓库是否有新的提交,直接 push 就好

  • 如果其他人已经有过提交,则会 push 失败,就用 git pull 拉取远程仓库的提交与把本地仓库的提交进行合并,然后再 push 一次

git pull包含git merge命令,会自动合并提交,如果遇到合并冲突,则需要手动合并。

9.Git的部分常用操作#

提交与修改#

为便于说明,接下来在目录中新建一些文本文件和目录,分别是empty.txtfile.txtreadme.md和用与存放图片的目录img

git add --添加文件到暂存区#

文件添加到暂存区后,Git会自动对文件更改进行跟踪。文件每次修改之后,如果需要提交,都要使用git add命令暂存到暂存区

git add empty.txt

可使用命令git status查看当前仓库的状态,显示有变更的文件,可以看到empty.txt被添加到了暂存区:

image-20221026191907624

添加多个文件到暂存区:

git add file.txt readme.md

添加整个img文件夹到暂存区:

git add img

添加当前目录全部文件到暂存区:

git add .

git commit --提交暂存区到本地仓库#

如果一个文件或文件的修改没有使用git add添加到暂存区进行追踪,那么git commit命令不会把它提交到仓库。

提交暂存区到本地仓库,使用-m附带提交说明

git commit -m "提交说明"

提交暂存区指定文件到本地仓库

git commit readme.md file2.txt -m "提交说明"

对于已添加到暂存区的文件(已跟踪的文件),可以跳过暂存区,直接提交文件在工作区的修改

git commit -a -m "提交说明"

git status --查看当前仓库的状态#

查看上次提交之后是否对文件有修改。
常见的状态有:

状态 说明
Changes to be committed 暂存区暂存的修改,等待被提交
Changes not staged for commit 文件在工作区已被修改,等待暂存
Untracked files 未添加到暂存区的文件

git diff --比较文件差异#

比较文件在暂存区和工作区的差异:

git diff file2.txt

比较暂存区和上一次提交的差异

git diff --cached file2.txt
或
git diff --staged file2.txt

比较两次提交的差异,需要使用两次提交的哈希值,哈希值可以通过git log获取。

git diff [hash1] [hash2]

可以使用代码编辑器例如VScode来对比文件差异,可以清楚地查看文件的不同之处

git rm --从暂存区删除文件#

从暂存区删除文件1.txt,不再跟踪它的变化,把它保留在工作区

git rm --cached 1.txt

从暂存区和工作区中删除文件1.txt

git rm 1.txt

git restore --恢复操作#

放弃在工作区对a.txt的修改,把暂存区的版本恢复到工作区

git restore a.txt
或
git checkout -- a.txt

放弃添加到暂存区的修改,恢复暂存区到添加前的状态,工作区不变:

git restore --staged a.txt
或
git reset HEAD

查看提交历史与回退版本#

git log --查看提交历史#

默认查看当前分支的历史;加--all 查看全部分支的历史

查看完整提交历史

git log

image-20221028162815764

提交记录的哈希值也叫提交ID。

查看最近两次的提交

git log -2

查看简短版的提交历史,哈希值被缩短了。为了方便,一般都使用简短的哈希值,它具有唯一性。

git log --oneline

image-20221028162859152

查看当前分支的可视化的提交历史:

git log --oneline --graph

image-20221028162024476

查看全部分支的可视化的提交历史。可以清楚地看到什么时候出现了分支、合并:

git log --oneline --graph --all

image-20221028163226363

git blame --查看指定文件的修改记录#

包括提交的哈希、作者名、提交日期

#git blame [文件地址] 例如:
git blame readme.md

git reset --回退版本#

重置命令git reset是Git最常用的命令之一,也是最危险,最容易误用的命令。

使用git reset命令,需要使用提交记录的哈希值,可以使用git log --oneline 命令获取某次提交(版本)的哈希值(提交ID)。哈希值是提交记录的绝对引用;如果知道要回退的版本与现在版本的距离,可以使用相对引用HEADHEAD可以被理解为“当前分支”,它默认指向当前所在分支的最新的提交,我们的工作都是在HEAD指向的位置上进行的,可以使用cat .git/HEAD查看当前HEAD的指向。HEAD^代表上一次提交,HEAD^^代表前上上一次提交,如果要向前N个版本,也可以使用HEAD~N来简写。

git reset命令的用法:
  • 带文件路径的用法:把暂存区的文件替换为指定commit的版本。

下面的命令是用最近一次提交的1.txt替换当前暂存区的1.txt,相当于取消git add 1.txt的操作

git reset HEAD 1.txt
  • 不带文件路径的用法:

    git reset [--soft | --mixed | --hard] [HEAD]/[哈希值]
    

根据soft,mixed,hard的不同,git resetHEAD(当前分支)、暂存区、工作区也有不同的影响:

git reset --hard 9d60796

当前分支回滚到哈希值9d60796指向的版本;暂存区被替换为9d60796的版本内容;工作区被替换为9d60796的版本内容。(工作区与暂存区未提交的代码会丢失)

git reset --soft 9d60796

当前分支回滚到9d60796的版本;不改变暂存区与工作区。

git reset --mixed 9d60796

当前分支回滚到9d60796的版本;暂存区被替换为9d60796的版本内容;不改变工作区。可以省略--mixed,不使用参数,默认为--mixed

总结来说:

--soft 用于撤销最近的提交,但保留所有的改动在暂存区,以便快速重新提交。
--mixed 也是撤销最近的提交,但它不仅移动HEAD指针,还把原本已暂存的改动放回到工作目录中,不再处于暂存状态,这样你有机会检查并选择性地重新暂存这些改动。

作者:sq800

出处:https://www.cnblogs.com/sq800/p/17301917.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   sq800  阅读(150)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示