Git教程
Git教程
Git介绍
开源的分布式版本控制系统,用于敏捷高效地处理任何大大小小的项目。
Git是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
其与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。
配置
Git 提供了一个叫做 git config
的命令,用来配置或读取相应的工作环境变量,这些环境变量,决定了 Git 在各个环节的具体工作方式和行为。
在 Windows 系统上,Git 会找寻用户主目录下的 .gitconfig 文件。主目录即 $HOME 变量指定的目录,一般都是 C:\Documents and Settings$USER。此外,Git 还会尝试找寻 /etc/gitconfig 文件,只不过看当初 Git 装在什么目录,就以此作为根目录来定位。
用户信息
配置个人的用户名称和电子邮件地址,这是为了在每次提交代码时记录提交者的信息:
1 | git config --global user.name "970640814" |
如果用了 –global 选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。如果要在某个特定项目中使用其他名字或者电邮,去掉–global选项重新配置即可,新的设定保存在当前项目的 .git/config 文件里。
文本编辑器
设置 Git 默认使用的文本编辑器,一般可能会是 Vi 或者 Vim,如果你有其他偏好,可以重新设置:
1 | git config --global core.editor "code --wait" |
差异分析工具
在解决合并冲突时使用哪种差异分析工具。比如要改用 vimdiff 的话:
1 | git config --global merge.tool vimdiff |
Git 可以理解 kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff 等合并工具的输出信息。
查看配置信息
可以使用git config --list
命令:
1 | $ git config --list |
有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 /etc/gitconfig 和 /.gitconfig),不过最终 Git 实际采用的是最后一个。这些配置我们也可以在 **/.gitconfig** 或 /etc/gitconfig 看到:
1 | vim ~/.gitconfig |
也可以直接查阅某个环境变量的设定,只要把特定的名字跟在后面即可:
1 | $ git config user.name |
生成SSH密钥
可以生成 SSH 密钥并添加到你的 Git 托管服务(如 GitHub、GitLab 等)上:
1 | ssh-keygen -t rsa -b 4096 -C "970640814@qq.com" |
查看版本
1 | git --version |
Git工作区、暂存区和版本库
- 工作区(Working Directory):就是你在电脑里能看到的目录。
- 暂存区(Staging Area):英文叫 stage 或 index。一般存放在 .git 目录下的 index 文件(.git/index)中。
- 版本库(Repository):工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库。
左侧为工作区,右侧为版本库。在版本库中标记为 “index” 的区域是暂存区(stage/index),标记为 “master” 的是 master 分支所代表的目录树。
“HEAD” 实际是指向 master 分支的一个”游标”,图示的命令中出现 HEAD 的地方可用 master 来替换。
objects 标识的区域为 Git 的对象库,实际位于 “.git/objects” 目录下,里面包含了创建的各种对象及内容。
当对工作区修改(或新增)的文件执行
git add
命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。当执行提交操作(
git commit
)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新,即 master 指向的目录树就是提交时暂存区的目录树。当执行
git reset HEAD
命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。当执行
git rm --cached <file>
命令时,会直接从暂存区删除文件,工作区则不做出改变。当执行
git checkout .
或者git checkout -- <file>
命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区中的改动。当执行
git checkout HEAD .
或者git checkout HEAD <file>
命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
工作区
本地计算机上的项目目录,你在这里进行文件的创建、修改和删除操作。工作区包含了当前项目的所有文件和子目录。
特点:
- 显示项目的当前状态。
- 文件的修改在工作区中进行,但这些修改还没有被记录到版本控制中。
暂存区
临时存储区域,它包含了即将被提交到版本库中的文件快照,在提交之前,你可以选择性地将工作区中的修改添加到暂存区。
特点:
- 暂存区保存了将被包括在下一个提交中的更改。
- 你可以多次使用
git add
命令来将文件添加到暂存区,直到你准备好提交所有更改。
常用命令:
1 | git add filename # 将单个文件添加到暂存区 |
版本库
包含项目的所有版本历史记录。每次提交都会在版本库中创建一个新的快照,这些快照是不可变的,确保了项目的完整历史记录。
特点:
- 版本库分为本地版本库和远程版本库,这里主要指本地版本库。
- 本地版本库存储在
.git
目录中,它包含了所有提交的对象和引用。
常用命令:
1 | git commit -m "Commit message" # 将暂存区的更改提交到本地版本库 |
工作区、暂存区和版本库之间的关系
1、工作区 -> 暂存区
使用 git add 命令将工作区中的修改添加到暂存区。
1 | git add filename |
2、暂存区 -> 版本库
使用 git commit 命令将暂存区中的修改提交到版本库。
1 | git commit -m "Commit message" |
3、版本库 -> 远程仓库
使用 git push 命令将本地版本库的提交推送到远程仓库。
1 | git push origin branch-name |
4、远程仓库 -> 本地版本库
使用 git pull 或 git fetch 命令从远程仓库获取更新。
1 | git pull origin branch-name |
Git工作流程
克隆仓库
1 | git clone https://github.com/970640814/970640814.github.io.git |
创建新分支
为了避免直接在 main 或 master 分支上进行开发,通常会创建一个新的分支:
1 | git checkout -b new-feature |
暂存文件
将修改过的文件添加到暂存区,以便进行下一步的提交操作:
1 | git add filename |
提交更改
将暂存区的更改提交到本地仓库,并添加提交信息:
1 | git commit -m "Add new feature" |
拉取最新更改
在推送本地更改之前,最好从远程仓库拉取最新的更改,以避免冲突:
1 | git pull origin main |
推送更改
将本地的提交推送到远程仓库:
1 | git push origin new-feature |
删除分支
如果不再需要新功能分支,可以将其删除:
1 | git branch -d new-feature |
或者从远程仓库删除分支:
1 | git push origin --delete new-feature |
Git创建仓库
git init
Git 使用 git init
命令来初始化一个 Git 仓库,Git 很多命令都需要在 Git 的仓库中运行,所以 git init
是使用 Git 的第一个命令。执行完成 git init
命令后,Git 仓库会生成一个 .git 目录,该目录包含了资源的所有元数据,其他的项目目录保持不变。
1 | # 创建并进入新目录 |
初始化后,会在 gitLearn 目录下会出现一个名为 .git 的目录,所有 Git 需要的数据和资源都存放在这个目录中。
如果当前目录下有几个文件想要纳入版本控制,需要先用 git add
命令告诉 Git 开始对这些文件进行跟踪,然后提交:
1 | git add *.py |
git clone
使用 git clone
从现有 Git 仓库中拷贝项目:
1 | git clone <repo> |
配置
git 的设置使用 git config
命令。
显示当前的 git 配置信息:
1 | $ git config --list |
编辑 git 配置文件:
1 | $ git config -e # 针对当前仓库 |
或者:
1 | $ git config -e --global # 针对系统上所有仓库 |
设置提交代码时的用户信息:
1 | $ git config --global user.name "970640814" |
如果去掉 –global 参数只对当前仓库有效。
Git基本操作
创建仓库命令
git 创建仓库命令:
命令 | 说明 |
---|---|
git init |
初始化仓库 |
git clone |
拷贝一份远程仓库,也就是下载一个项目。 |
提交与修改
Git 的工作就是创建和保存你的项目的快照及与之后的快照进行对比。
有关创建与提交项目快照的命令:
命令 | 说明 |
---|---|
git add |
添加文件到暂存区 |
git status |
查看仓库当前的状态,显示有变更的文件。 |
git diff |
比较文件的不同,即暂存区和工作区的差异。 |
git difftool |
使用外部差异工具查看和比较文件的更改。 |
git range-diff |
比较两个提交范围之间的差异。 |
git commit |
提交暂存区到本地仓库。 |
git reset |
回退版本。 |
git rm |
将文件从暂存区和工作区中删除。 |
git mv |
移动或重命名工作区文件。 |
git notes |
添加注释。 |
git checkout |
分支切换。 |
git switch (Git 2.23 版本引入) |
更清晰地切换分支。 |
git restore (Git 2.23 版本引入) |
恢复或撤销文件的更改。 |
git show |
显示 Git 对象的详细信息。 |
提交日志
命令 | 说明 |
---|---|
git log |
查看历史提交记录 |
git blame <file> |
以列表形式查看指定文件的历史修改记录 |
git shortlog |
生成简洁的提交日志摘要 |
git describe |
生成一个可读的字符串,该字符串基于 Git 的标签系统来描述当前的提交 |
远程操作
命令 | 说明 |
---|---|
git remote |
远程仓库操作 |
git fetch |
从远程获取代码库 |
git pull |
下载远程代码并合并 |
git push |
上传远程代码并合并 |
git submodule |
管理包含其他 Git 仓库的项目 |
文件状态的转换流程
未跟踪(Untracked): 新创建文件最初是未跟踪的。它们存在于工作目录中,但没有被 Git 跟踪。
1 | touch newfile.txt # 创建一个新文件 |
已跟踪(Tracked): 通过 git add
命令将未跟踪的文件添加到暂存区后,文件变为已跟踪状态。
1 | git add newfile.txt # 添加文件到暂存区 |
已修改(Modified): 对已跟踪的文件进行更改后,这些更改会显示为已修改状态,但这些更改还未添加到暂存区。
1 | echo "Hello, World!" > newfile.txt # 修改文件 |
已暂存(Staged): 使用 git add
命令将修改过的文件添加到暂存区后,文件进入已暂存状态,等待提交。
1 | git add newfile.txt # 添加文件到暂存区 |
已提交(Committed): 使用 git commit
命令将暂存区的更改提交到本地仓库后,这些更改被记录下来,文件状态返回为已跟踪状态。
1 | git commit -m "Added newfile.txt" # 提交更改 |
Git分支管理
Git 分支管理是 Git 强大功能之一,能够让多个开发人员并行工作,开发新功能、修复 bug 或进行实验,而不会影响主代码库。
几乎每一种版本控制系统都以某种形式支持分支,一个分支代表一条独立的开发线。使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。Git 分支实际上是指向更改快照的指针。
创建分支
创建新分支并切换到该分支:
1 | git checkout -b <branchname> |
切换分支命令:
1 | git checkout (branchname) |
查看分支
查看所有分支:
1 | git branch |
查看远程分支:
1 | git branch -r |
查看所有本地和远程分支:
1 | git branch -a |
合并分支
将其他分支合并到当前分支:
1 | git merge <branchname> |
解决合并冲突
当合并过程中出现冲突时,Git 会标记冲突文件,你需要手动解决,打开冲突文件,按照标记解决冲突。
删除分支
删除本地分支:
1 | git branch -d <branchname> |
强制删除未合并的分支:
1 | git branch -D <branchname> |
删除远程分支:
1 | git push origin --delete <branchname> |
实例
1 | 97064@▒▒Ҳ MINGW64 /d/Git/projects |
命令手册
命令 | 说明 | 用法示例 |
---|---|---|
git branch |
列出、创建或删除分支。它不切换分支,只是用于管理分支的存在。 | git branch :列出所有分支 git branch new-branch :创建新分支 git branch -d old-branch :删除分支 |
git checkout |
切换到指定的分支或恢复工作目录中的文件。也可以用来检出特定的提交。 | git checkout branch-name :切换分支 git checkout file.txt :恢复文件到工作区 git checkout <commit-hash> :检出特定提交 |
git switch |
专门用于切换分支,相比 git checkout 更加简洁和直观,主要用于分支操作。 |
git switch branch-name :切换到指定分支 git switch -c new-branch :创建并切换到新分支 |
git merge |
合并指定分支的更改到当前分支。 | git merge branch-name :将指定分支的更改合并到当前分支 |
git mergetool |
启动合并工具,以解决合并冲突。 | git mergetool :使用默认合并工具解决冲突 git mergetool --tool=<tool-name> :指定合并工具 |
git log |
显示提交历史记录。 | git log :显示提交历史 git log --oneline :以简洁模式显示提交历史 |
git stash |
保存当前工作目录中的未提交更改,并将其恢复到干净的工作区。 | git stash :保存当前更改 git stash pop :恢复最近保存的更改 git stash list :列出所有保存的更改 |
git tag |
创建、列出或删除标签。标签用于标记特定的提交。 | git tag :列出所有标签 git tag v1.0 :创建一个新标签 git tag -d v1.0 :删除标签 |
git worktree |
允许在一个仓库中检查多个工作区,适用于同时处理多个分支。 | git worktree add <path> branch-name :在指定路径添加新的工作区并切换到指定分支 git worktree remove <path> :删除工作区 |
Git查看提交历史
Git 提供了多种命令和选项来查看提交历史,从简单的日志到详细的差异对比。一般常用两个命令:
git log
- 查看历史提交记录。git blame <file>
- 以列表形式查看指定文件的历史修改记录。
git log
在使用 Git 提交若干更新后,又或者克隆了某个项目,想回顾下提交历史,可以使用 git log
命令查看。
git log
命令用于查看 Git 仓库中提交历史记录。显示了从最新提交到最早提交的所有提交信息,包括提交的哈希值、作者、提交日期和提交消息等。基本语法:git log [选项] [分支名/提交哈希]
常用的选项包括:
-p
:显示提交的补丁(具体更改内容)。--oneline
:以简洁的一行格式显示提交信息。--graph
:以图形化方式显示分支和合并历史。--decorate
:显示分支和标签指向的提交。--author=<作者>
:只显示特定作者的提交。--since=<时间>
:只显示指定时间之后的提交。--until=<时间>
:只显示指定时间之前的提交。--grep=<模式>
:只显示包含指定模式的提交消息。--no-merges
:不显示合并提交。--stat
:显示简略统计信息,包括修改的文件和行数。--abbrev-commit
:使用短提交哈希值。--pretty=<格式>
:使用自定义的提交信息显示格式。
示例:
1 | $ git log |
git blame
git blame
命令用于逐行显示指定文件的每一行代码是由谁在什么时候引入或修改的。可以追踪文件中每一行的变更历史,包括作者、提交哈希、提交日期和提交消息等信息。格式如下:git blame [选项] <文件路径>
常用的选项包括:
-L <起始行号>,<结束行号>
:只显示指定行号范围内的代码注释。-C
:对于重命名或拷贝的代码行,也进行代码行溯源。-M
:对于移动的代码行,也进行代码行溯源。-C -C
或-M -M
:对于较多改动的代码行,进行更进一步的溯源。--show-stats
:显示包含每个作者的行数统计信息。
1 | # 显示文件每一行的代码注释和相关信息: |
恢复和回退
提供了多种方式来恢复和回退到之前的版本,不同的命令适用于不同的场景和需求,几种常见的方法:
git checkout
:切换分支或恢复文件到指定提交。git reset
:重置当前分支到指定提交(软重置、混合重置、硬重置)。git revert
:创建一个新的提交以撤销指定提交,不改变提交历史。git reflog
:查看历史操作记录,找回丢失的提交。
1、git checkout:检查出特定版本的文件
用于切换分支或恢复工作目录中的文件到指定的提交。
1 | # 恢复工作目录中的文件到某个提交: |
这种方式切换到特定的提交时,处于分离头指针(detached HEAD)状态。
2、git reset:重置当前分支到特定提交
可以更改当前分支的提交历史,它有三种主要模式:–soft、–mixed 和 –hard。
–soft:只重置 HEAD 到指定的提交,暂存区和工作目录保持不变。
1 | git reset --soft <commit> |
–mixed(默认):重置 HEAD 到指定的提交,暂存区重置,但工作目录保持不变。
1 | git reset --mixed <commit> |
–hard:重置 HEAD 到指定的提交,暂存区和工作目录都重置。
1 | git reset --hard <commit> |
例如,将当前分支重置到 abc123 提交:
1 | git reset --hard abc123 |
3、git revert:撤销某次提交
创建一个新的提交,用来撤销指定的提交,它不会改变提交历史,适用于已经推送到远程仓库的提交。
1 | git revert <commit> |
4、git reflog:查看历史操作记录
git reflog 命令记录了所有 HEAD 的移动。即使提交被删除或重置,也可以通过 reflog 找回。利用 reflog 可以找到之前的提交哈希,从而恢复到特定状态。
1 | git reflog |
Git标签
达到一个重要的阶段,并希望永远记住提交的快照,你可以使用 git tag
给它打上标签。Git 标签(Tag)用于给仓库中的特定提交点加上标记,通常用于发布版本(如 v1.0, v2.0)。
-a
选项意为”创建一个带注解的标签”,不用 -a 选项也可以执行的,但不会记录这标签是啥时候打的,谁打的,也不会让你添加个标签的注解,我们推荐一直创建带注解的标签。标签语法:git tag <tagname>
1 | $ git tag -a v1.0 |
推送标签到远程仓库
默认情况下,git push 不会推送标签,你需要显式地推送标签。
1 | git push origin <tagname> |
推送所有标签:
1 | git push origin --tags |
删除轻量标签
本地删除:
1 | git tag -d <tagname> |
远程删除:
1 | git push origin --delete <tagname> |
附注标签
附注标签存储了创建者的名字、电子邮件、日期,并且可以包含标签信息。附注标签更为正式,适用于需要额外元数据的场景。
1 | # 创建附注标签语法: |
Git进阶操作
交互式暂存(Interactive Staging):逐块选择要暂存的更改,精细控制提交内容。
git add
命令可以选择性地将文件或文件的一部分添加到暂存区,这在处理复杂更改时非常有用。
使用**git add -p
**:逐块选择要暂存的更改。执行此命令后,Git 会逐块显示文件的更改,你可以选择是否暂存每个块。常用选项包括:
y
:暂存当前块n
:跳过当前块s
:拆分当前块e
:手动编辑当前块q
:退出暂存
Git Stash:临时保存工作进度
允许你临时保存当前工作目录的更改,以便你可以切换到其他分支或处理其他任务。
1 | # 保存当前工作进度: |
Git Rebase:变基
git rebase
命令用于将一个分支上的更改移到另一个分支之上。它可以帮助保持提交历史的线性,减少合并时的冲突。
变基当前分支到指定分支:
1 | git rebase <branchname> |
交互式变基:
1 | git rebase -i <commit> |
允许你在变基过程中编辑、删除或合并提交。常用选项包括:
pick
:保留提交reword
:修改提交信息edit
:编辑提交squash
:将当前提交与前一个提交合并fixup
:将当前提交与前一个提交合并,不保留提交信息drop
:删除提交
Git Cherry-Pick:拣选提交
允许你选择特定的提交并将其应用到当前分支。它在需要从一个分支移植特定更改到另一个分支时非常有用。
拣选提交:
1 | git cherry-pick <commit> |
处理拣选冲突:如果拣选过程中出现冲突,解决冲突后使用 git cherry-pick --continue
继续拣选。
Git远程仓库(Github)

添加远程库
要添加一个新的远程仓库,可以指定一个简单的名字,以便将来引用,命令格式如下:
1 | git remote add [shortname] [url] |
由于本地 Git 仓库和 GitHub 仓库之间的传输是通过SSH加密的,所以需要配置验证信息(之后会要求确认路径和输入密码,这使用默认的一路回车就行):
1 | $ ssh-keygen -t rsa -C "970640814@qq.com" |
成功的话会在 ~/ 下生成 .ssh 文件夹,进去,打开 id_rsa.pub,复制里面的 key。
回到 github 上,进入 Account => Settings(账户配置),左边选择 SSH and GPG keys,然后点击 New SSH key 按钮,title 设置标题,可以随便填,粘贴在你电脑上生成的 key。
为了验证是否成功,输入以下命令:
1 | $ ssh -T git@github.com |
之后登录后点击” New repository “:
之后在在Repository name 填入testDemo(远程仓库名) ,其他保持默认设置,点击”Create repository”按钮,就成功地创建了一个新的Git仓库:
创建成功后,显示如下信息:
以上信息说明可以从这个仓库克隆出新的仓库,也可以把本地仓库的内容推送到GitHub仓库。
根据 GitHub 的提示,在本地的仓库下运行命令:
1 | $ mkdir testDemo |
查看当前远程库
1 | $ git remote |
提交远程仓库
1 | # 1、从远程仓库下载新分支与数据,该命令执行完后需要执行 git merge 远程分支到你所在的分支。 |
假设你配置好了一个远程仓库,并且想要提取更新的数据,你可以首先执行 git fetch [alias] 告诉 Git 去获取它有你没有的数据,然后可以执行 git merge [alias]/[branch] 以将服务器上的任何更新(假设有人这时候推送到服务器了)合并到你的当前分支。
接下来我们在 Github 上点击” README.md” 并在线修改它:
然后我们在本地更新修改:
1 | $ git fetch origin |
以上信息”2b647fb..7fe3b78 master -> origin/master” 说明 master 分支已被更新,我们可以使用以下命令将更新同步到本地:
1 | $ git merge origin/master |
推送到远程仓库
推送你的新分支与数据到某个远端仓库命令:
1 | # 将你的 [branch] 分支推送成为 [alias] 远程仓库上的 [branch] 分支 |
删除远程仓库
删除远程仓库你可以使用命令:
1 | git remote rm [别名] |