当前位置:   article > 正文

Git(版本控制系统)

Git(版本控制系统)
Git --- 分布式
  • 分布式的区别,

每个人的电脑都是服务器,当你从主仓库拉取一份代码下来后,你的电脑就是服务器,无需担心主仓库被删或者找不到的情况,你可以自由在本地回滚,提交;当你想把自己的代码提交到主仓库时,只需要合并推送到主仓库就可以了,同时你可以把自己的代码新建一份仓库分享给其它人。

Svn 、Csv --- 集中式

  • 集中式的区别,

版本控制系统每次在写代码时都需要从服务器中拉取一份下来,并且如果服务器丢失了,那么所有的就都丢失了,你本机客户端仅保存当前的版本信息;集中式就是把代码放在一个服务器上集中管理,你的所有回滚等操作都需要服务器的支持。

  • 版本号问题,

像集中式它们都有一个主版本号,所有的版本迭代都以这个版本号为主,而分布式因为每个客户端都是服务器,git没有固定的版本号,但是有一个由哈希算法算出的id,用来回滚用的,同时也有一个master仓库,这个仓库是一切分支仓库的主仓库,我们可以推送提交到master并合并到主仓库上,主仓库的版本号会迭代一次,我们客户端上的git版本号无论迭代多少次,都跟master无关,只有合并时,master才会迭代一次。

基础仓库管理

1、git config

配置git环境

git config --global

  • config:参数是用来配置git环境的

  • --global:长命令表示配置整个git环境

初次使用git需要设置你的用户名以及邮箱,这将作为当前机器git的标识

用户名配置

git config --global user.name "你的用户名"

邮箱配置

git config --global user.email "你的邮箱"

2、git init

初始化一个新的 Git 仓库

git init 是 Git 版本控制系统中的一个基本命令,用于在一个已存在的目录中初始化一个新的 Git 仓库。当你想要对某个项目或目录进行版本控制时,首先需要在这个项目或目录的根目录下执行 git init 命令。

这个命令会创建一个名为 .git 的隐藏目录(在 Unix-like 系统中,以点.开头的目录或文件是隐藏的),这个目录包含了 Git 仓库的所有元数据,如配置信息、分支信息、提交历史等。

  • 文件夹
  1. hooks:存储 Git 钩子的目录。钩子是在特定事件发生时触发的脚本,如提交前、提交后等。Git 提供了许多预定义的钩子模板,用户也可以根据需要自定义钩子脚本。

  2. info:包含一些辅助性的信息文件,如 exclude 文件(用于定义需要被忽略但又不希望放在全局 .gitignore 文件中的文件)。

  3. logs:存储了每个引用(分支、标签等)的修改历史。这些日志对于审计和调试版本控制历史非常有用。

  4. objects:存储了 Git 仓库的对象(commits、trees 和 blobs)。这是 Git 仓库的核心部分,保存了项目的完整历史记录和元数据。objects 文件夹下的文件以 SHA-1 哈希值命名,用于唯一标识每个对象。

    1. blob 对象:存储文件数据,每个文件都会被存储为一个 blob 对象。

    2. tree 对象:存储树形结构,每个目录会被存储为一个 tree 对象,tree 对象包含了指向文件 blob 对象和子目录 tree 对象的指针。

    3. commit 对象:存储提交信息,每个提交都会被存储为一个 commit 对象,commit 对象包含了指向根目录 tree 对象、父提交、提交者信息、提交时间等信息的指针。

    4. tag 对象:存储标签信息,每个标签都会被存储为一个 tag 对象,tag 对象包含了指向某个 commit 对象、标签名、标签作者、标签信息等信息的指针。

  5. refs:存储了所有的引用(分支、标签等)。refs 文件夹下通常包含 headsremotestags 子文件夹,分别用于存储本地分支、远程分支和标签的信息。

  6. packed-refs(如果存在):这是一个文件,用于存储压缩的引用信息,以减少 .git 目录的大小。

  • 文件
  1. HEAD:指向当前所在的分支(或者是一个特定的提交)。它是一个符号引用,通常指向 refs/heads/<branchname>,表示当前检出的分支。

  2. config:存储了项目级别的 Git 配置信息,包括用户名、邮箱、远程仓库地址等。这些信息可以通过 git config 命令进行设置或修改。

  3. description:对于非空的 Git 仓库,这个文件通常包含了对项目的简短描述。这个文件主要用于 GitWeb 或其他基于 Web 的 Git 仓库浏览器。

  4. index(或称为 .git/indexstagecache):包含了暂存区(staging area)的内容,记录了即将提交的文件和相关元数据。它是 Git 用来准备下一次提交的快照。

  5. COMMIT_EDITMSG(在某些操作中可能出现):在执行某些 Git 命令(如 git commit --amend)时,Git 会使用这个文件来存储默认的提交消息,供用户编辑。

  6. gitk.cache(如果存在):这是 Gitk(Git 的图形界面工具)使用的缓存文件,用于提高性能。

需要注意的是,.git 目录下的文件和文件夹可能会随着 Git 版本的更新而有所变化,但上述内容涵盖了 .git 目录中最常见和最重要的部分。通常,用户不需要直接操作 .git 目录下的内容,而是通过 Git 命令和工具来管理和操作仓库。

文件管理

1、git add

将文件添加到暂存区(staging area)

可以添加单个文件或整个目录

  • git add filename.txt

  • git add . --- # 添加当前目录下的所有文件(包括新文件和已修改的文件),不包括被 .gitignore 忽略的文件

  • git add -Agit add --all (Git2.22版本之前) # 添加所有更改(包括新文件、已修改的文件、已删除的文件以及新目录),忽略 .gitignore 文件

  1. 添加忽略规则:在 .gitignore 文件中,你可以添加需要忽略的文件或目录的规则。每行一个规则,可以使用通配符(如 *)和特殊字符来匹配多个文件或目录。以下是一些示例规则:

    1. # 这是一个注释,Git 会忽略它

    2. *.log:忽略所有以 .log 结尾的文件。

    3. /build/:忽略根目录下的 build 文件夹及其所有内容。

    4. !/build/lib/:但不忽略 build/lib/ 目录下的内容(注意,这条规则需要放在忽略 build/ 目录的规则之后)。

2、git commit

将暂存区的更改提交到仓库中,并附加一条提交信息来描述你的更改:

git commit -m "提交信息"

其他选项
  • --amend:如果你刚刚做了一次提交,但想要修改提交信息或添加一些遗漏的文件到这个提交中,你可以使用 --amend 选项。这会修改最近的提交,而不是创建一个新的提交。

git commit --amend -m "更新提交信息"

  • -a--all:这个选项允许你直接提交所有已经跟踪(tracked)文件的更改,而不需要先使用 git add 命令。但是,它不会添加新文件到仓库中,新文件仍然需要使用 git add 命令。

git commit -a -m "提交所有已跟踪文件的更改"

  • --dry-run-n:这个选项会让 git commit 显示将要进行的操作,但不会真正提交更改。这对于预览提交信息或确保没有遗漏的文件非常有用。

git commit --dry-run

3、git status

显示当前工作目录和暂存区的状态

Git 会检查你的工作目录和暂存区(也称为索引或暂存区),然后报告出哪些文件已经被修改、哪些文件已经被添加到暂存区准备提交、以及哪些文件还未被 Git 跟踪(即尚未纳入版本控制的新文件)。

git status 命令的输出可能会包含以下几类信息:

  1. 当前分支和远程分支的状态:显示你当前所在的分支以及是否有远程分支的跟踪信息,以及它们之间是否同步(是否有推送或拉取的需要)。

  2. 未跟踪的文件:这些是新创建的文件,但还没有被 Git 添加到版本控制中。Git 会列出这些文件的名称,并提示你可以使用 git add 命令来开始跟踪这些文件。

  3. 已修改但尚未暂存的文件:这些文件已经被修改,但修改后的版本还没有被添加到暂存区。Git 会列出这些文件的名称,并提示你可以使用 git add 命令来将修改后的版本添加到暂存区。

  4. 已暂存但尚未提交的文件:这些文件已经被添加到暂存区,但还没有被提交到仓库中。Git 会列出这些文件的名称,并提示你可以使用 git commit 命令来提交这些文件到仓库中。

  5. 有冲突的文件:如果你在合并或变基(rebase)过程中遇到了冲突,Git 会特别指出哪些文件存在冲突,并提示你需要手动解决这些冲突。

4、git diff

比较工作区与暂存区、暂存区与最新提交之间的差异。

基本用法
  • 显示工作目录与暂存区之间的差异: 如果你已经使用 git add 命令将更改添加到了暂存区,但还没有提交,你可以使用 git diff 来查看工作目录中已修改但尚未暂存的文件与暂存区之间的差异。但是,默认情况下,如果文件已经被暂存(即使用 git add 添加),git diff 不会显示这些文件的差异。

git diff

显示暂存区与最后一次提交之间的差异: 使用 --cached--staged 选项可以查看暂存区(即准备提交的更改)与最后一次提交之间的差异。

git diff --cached # 或者 git diff --staged

比较两个提交之间的差异: 你也可以使用 git diff 来比较两个不同提交之间的差异。

git diff <commit-id1> <commit-id2>

5、git rm

用于从工作目录和暂存区(staging area)中删除文件

  1. 删除单个文件:

git rm example.txt

这会从工作目录和暂存区中删除 example.txt 文件。

2、递归删除目录:

git rm -r my_directory/

这会删除 my_directory 目录及其中的所有文件和子目录。

3、忽略删除操作(仅从暂存区中删除,保留工作目录中的文件):

git rm --cached some_file.txt

然后,将 some_file.txt 添加到 .gitignore 文件中,以避免未来的更改被 Git 跟踪。

6、git mv

用于移动或重命名文件、目录,并且这个操作会被 Git 跟踪为一次修改

基本用法

git mv [options] <source> <destination>

  • <source> 是你想要移动或重命名的文件或目录的当前名称。

  • <destination> 是你希望文件或目录被移动或重命名后的新名称(如果路径改变的话,还包括新路径)。

  • [options] 代表可选的参数,实际上并不经常需要额外的选项

示例
  1. 重命名文件

  2. 假设你有一个名为 oldname.txt 的文件,你想将其重命名为 newname.txt

git mv oldname.txt newname.txt

执行这个命令后,oldname.txt 将被重命名为 newname.txt,并且这个变化会被 Git 跟踪。

  1. 移动文件

  2. 如果你想要将文件从一个目录移动到另一个目录,并可能同时重命名它,你可以这样做:

git mv source/oldname.txt target/newname.txt

这个命令会将 source/oldname.txt 移动到 target/ 目录下,并将其重命名为 newname.txt。

分支管理

1、git branch

用于操作分支

基本用法
  • git branch 列出所有本地分支(当前分支前面会有一个星号(*)标记)

  • git branch -r 列出所有远程分支

  • git fetch --all 或 git branch -a 列出所有本地和远程分支

  • git branch <新分支名> 基于当前分支创建新分支(只创建新分支)

  • git checkout -b <新分支名> 创建并切换到新分支

  • git switch -c <新分支名> 创建并切换到新分支(Git 2.23+ )

  • git branch -d <分支名> 删除本地分支

  • git branch -D <分支名> 强制删除本地分支(即使它尚未合并)

  • git branch -m [旧分支名] [新分支名] 重命名分支

2、git switch

用于切换分支(Git 2.23 版本及以上使用)

基本用法

git switch <分支名>

切换到已存在的分支(如果指定的分支不存在,Git 会报错)

git switch -c <新分支名>

创建并切换到新分支(基于当前分支) 或者 git switch --create <新分支名>

与 git checkout 的对比:

Git 2.23 之前的版本中,git checkout 用于多种目的:

  • 检出文件:使用 git checkout <文件路径> 来恢复工作目录中文件的特定版本。

  • 撤销工作目录的更改:使用 git checkout -- <文件路径> 来撤销对工作目录中文件的更改(注意这里的 -- 很重要,它区分了检出文件和切换分支/检出分支)。

  • 切换分支:在 Git 2.23 之前,使用 git checkout <分支名> 来切换分支。但从 Git 2.23 开始,推荐使用 git switch <分支名> 来切换分支,以保持命令的清晰性。

3、git checkout

用于切换分支

基本用途
  1. 切换分支:git checkout 最常见的用途之一是在不同的分支之间切换。当你想要在一个新的分支上工作时,或者需要查看另一个分支上的代码时,你可以使用 git checkout 命令。

git checkout <branch-name>

从 Git 2.23 开始,这个用途被 git switch 命令所取代。

2、检出文件:git checkout 也可以用来检出(即恢复)工作目录中的文件到它们最近的提交状态。这可以用来撤销对文件的修改。

git checkout -- <file-path>

注意:在 Git 2.23 及以后的版本中,这个用途被 git restore 命令所取代。

3、检出新的分支:虽然这实际上是切换分支的一个特例,但 git checkout 也可以用来创建一个新的分支并立即切换到它。

git checkout -b <new-branch-name>

这个命令是 git branch <new-branch-name> 和 git checkout <new-branch-name> 的组合。

4、git rebase

将一个分支的修改整合到另一个分支上,保持提交历史的线性

基本原理

当执行 git rebase 命令时,Git 会执行以下操作:

  1. 找到两个分支(当前分支和指定分支)的共同祖先。

  2. 将当前分支上自共同祖先以来的所有提交保存为临时文件。

  3. 将当前分支指向指定分支的最新提交。

  4. 将之前保存的提交重新应用到当前分支的最新提交上,生成新的提交记录。

解决冲突

如果在变基过程中发生冲突,

  • Git 会暂停变基进程,并提示你解决冲突。

  • 解决冲突后,你需要使用 git add 命令将修改的文件添加到暂存区,

  • 然后执行 git rebase --continue 来继续变基操作。

  • 如果希望放弃当前的变基操作并恢复到原始状态,可以使用 git rebase --abort

注意事项
  1. 改变提交历史:git rebase 会改变提交的顺序和哈希值,因此它只适用于本地分支。

在公共分支上使用 git rebase 可能会导致其他协作者遇到问题。

  1. 强制推送:在将变基后的分支推送到远程仓库时,由于提交历史已经改变,你可能需要使用强制推送(git push --forcegit push --force-with-lease)来覆盖远程分支上的历史。

5、git merge

用于合并两个或多个开发历史(即分支)的命令

使用 git merge 命令将 feature-branch 分支上的更改合并到 main 分支。

git merge feature-branch

合并冲突

如果 main 分支和 feature-branch 分支中的文件在相同位置进行了不同的更改,Git 将无法自动合并这些更改,并会提示你解决合并冲突。解决合并冲突的过程包括:

  1. 查看冲突文件:Git 会列出所有包含冲突的文件。

  2. 解决冲突:你需要手动编辑这些文件,以解决冲突。Git 会在冲突的位置添加特殊的标记来指示哪些更改来自哪个分支。

  3. 标记冲突为已解决:解决完所有冲突后,你需要使用 git add 命令将冲突文件标记为已解决。

  4. 完成合并:最后,使用 git commit 命令来完成合并过程,Git 会创建一个新的合并提交来记录合并操作。

历史记录查看

1、git log

显示项目中的提交历史记录

基本用法
  • git log

列出当前分支上从最新到最旧的所有提交,包括提交哈希值(commit hash)、提交者信息、提交日期和提交信息。

  • git log --oneline

提交信息压缩成一行显示,通常只显示哈希值的前几个字符和提交信息。

  • git log -n <数量>

  • git log --since="2 weeks ago"

  • git log --author="<作者名>"

  • git log -- <文件路径>

  • git log --merges 查看所有合并提交

2、git reflog

记录了本地仓库中 HEAD 和分支引用所指向的更新历史

包括了你所有的 commit 操作、reset 操作、checkout 操作、merge 操作、rebase 操作等,以及这些操作导致的 HEAD 和分支引用的变化。

使用场景
  • 恢复丢失的提交:如果你不小心执行了 git reset --hardgit checkout 命令,导致丢失了某些提交,你可以通过 git reflog 找到这些提交的历史记录,并使用 git resetgit checkout 命令来恢复它们。

  • 审查过去的操作:git reflog 可以帮助你审查和理解你的仓库在过去一段时间内的操作历史,这对于调试和了解项目的变化过程非常有帮助。

  • 分析工作流程:通过分析 git reflog 输出,你可以评估你的 Git 工作流程,看看是否有改进的空间,比如减少不必要的分支切换或合并操作。

示例

假设你执行了一系列操作后,不小心丢失了一些提交。你可以通过以下步骤来恢复它们:

  1. 查看 reflog:

git reflog

  1. 这将列出 HEAD 和分支引用的变更历史。每一行都包含了一个操作的简短描述、对应的 HEAD 位置(即提交哈希)和操作发生的时间戳。

  2. 找到丢失的提交: 在 git reflog 的输出中,找到你丢失的提交对应的哈希值。这通常需要你根据时间戳和操作描述来识别。

  3. 恢复提交: 一旦你找到了丢失的提交的哈希值,你可以使用 git resetgit checkout(对于旧版本的 Git)命令来恢复这个提交。如果你想要将这个提交作为一个新的分支的开始,可以使用 git branch new-branch-name <commit-hash> 命令。

注意事项
  • git reflog 记录的是本地仓库的引用变化,不会推送到远程仓库。

  • 默认情况下,Git 会保留一段时间内的 reflog 记录,但你可以通过配置 gc.reflogExpiregc.reflogExpireUnreachable 来调整这个时间。

3、git show

用于显示 Git 仓库中特定对象(如提交、标签等)的信息

基本用法
查看最近一次提交的详细信息:
  • 只需在命令行中输入 git show,不加任何参数,Git 就会显示当前分支上最近一次提交的详细信息。

查看特定提交的详细信息:
  • 如果你知道想要查看的提交的哈希值(或部分哈希值),可以使用 git show [commit-hash] 来查看该提交的详细信息。例如:

git show a1b2c3d

  • 这里 [commit-hash] 是你想要查看的提交的哈希值。

查看特定分支上某个提交的详细信息:
  • 虽然通常不需要显式指定分支名,因为 git show 会根据你当前所在的分支或提供的提交哈希值来工作,但如果你想要确保从特定分支查看提交,可以结合使用 git log 来找到提交哈希值,然后使用 git show

显示内容

git show 显示的内容通常包括:

  • 提交信息:包括提交者姓名、邮箱、提交日期、提交信息(即提交时输入的说明)。

  • 差异(diff):显示该提交引入的更改。默认情况下,这将是该提交与其父提交之间的差异,但如果这是一个合并提交,则可能会显示更复杂的差异。

高级用法
  • 查看合并提交的详细信息:

  • 合并提交通常包含多个父提交。git show 会默认显示与第一个父提交的差异,但你可以使用 --cc--combined 选项来查看合并提交引入的所有更改的合并差异。

  • 使用 --stat 选项:

  • 如果你只对更改的统计信息感兴趣(比如哪些文件被修改了,每个文件有多少行被添加或删除),可以使用 --stat 选项。例如:

git show --stat a1b2c3d

  • 使用 --name-only 选项:

  • 如果你只想知道哪些文件被修改了,而不关心具体的更改统计信息,可以使用 --name-only 选项。

远程操作

1、git remote

可以查看、添加、删除、重命名或修改远程仓库的信息

  1. 查看当前配置的远程仓库:

git remote 或者 git remote -v

-v 选项会显示远程仓库的URL以及它们分别对应的别名(如origin)。

2、添加新的远程仓库:

git remote add [别名] [URL]

其中 [别名] 是你给远程仓库起的名字(如origin),[URL] 是远程仓库的地址。

例如,要添加一个名为 upstream 的远程仓库,你可以使用:

git remote add upstream https://github.com/user/repo.git

3、删除远程仓库:

git remote remove [别名] 或者简写为: git remote rm [别名]

4、重命名远程仓库:

Git本身没有直接的命令来重命名远程仓库,但你可以通过先删除再添加的方式来实现:

git remote rename [旧别名] [新别名]

5、修改远程仓库的URL: 修改远程仓库的URL通常通过 git remote set-url 命令完成:

git remote set-url [别名] [新的URL]

如果你想要同时修改push和fetch的URL,可以使用上面的命令。

如果只想修改其中一个,可以使用 --push 或 --fetch 选项。

6、查看远程仓库的详细信息: 使用 git remote show [别名]

可以查看特定远程仓库的详细信息,包括它的URL、远程分支以及本地跟踪分支等。

2、git push

用于将本地的分支更改推送到远程仓库中

git push <远程仓库名> <分支名>

  • <远程仓库名> 是你给远程仓库设置的名称,默认情况下,当你克隆一个仓库时,Git 会自动将远程仓库命名为 origin。

  • <分支名> 是你想要推送的本地分支的名称。如果你想推送当前分支到与远程仓库中同名的分支,可以省略 <分支名>,直接写 git push <远程仓库名>

git push --force

  • 强制推送 --force 选项会覆盖远程分支的历史,这可能会导致其他协作者的工作丢失或出现问题。因此,仅在确实需要时才使用它,并且最好先与团队成员沟通。

推送并删除远程分支:

如果你想要删除远程仓库中的一个分支,可以使用 :(冒号)后跟远程分支名的方式来实现:

git push origin :<branch-name>

请注意,这不会删除你本地的分支,只会删除远程仓库中的分支。

注意:
  • 在推送之前,请确保你的本地仓库是最新的,即已经通过 git pullgit fetch 获取了远程仓库的最新更改,并解决了可能出现的任何合并冲突。

3、git pull

从远程仓库获取最新的更改,并将这些更改合并到当前的工作分支中

  • 这个命令实际上是 git fetchgit merge 两个命令的简写,它首先会从远程仓库获取最新的历史记录,然后尝试将远程仓库的更改合并到你的当前分支中。

git pull <远程仓库名> <分支名>

  • <远程仓库名> 是你给远程仓库设置的名称,默认情况下,当你克隆一个仓库时,Git 会自动将远程仓库命名为 origin

  • <分支名> 是你想要拉取的远程分支的名称。如果你省略这个参数,Git 会尝试拉取与当前分支有追踪关系的远程分支。

  • 在执行 git pull 之前,最好先确保你的工作目录是干净的,即没有未提交的更改。如果有未提交的更改,Git 可能会阻止你拉取远程更改,或者在合并时产生冲突。

  • 如果拉取远程更改时出现了合并冲突,Git 会暂停合并过程,并让你解决冲突。解决冲突后,你需要使用 git add 命令将解决后的文件添加到暂存区,并使用 git commit 命令完成合并提交。

4、git clone

从远程仓库复制一个项目的完整历史记录到本地

创建一个新的目录(如果目录名没有指定,则默认为远程仓库的名称),并在该目录中初始化一个新的 Git 仓库,然后将远程仓库中的所有文件和目录复制到该仓库中。

git clone <仓库URL> [<目录名>]

  • <仓库URL> 是你想要克隆的远程仓库的 URL 地址。这个地址可以是 HTTP、HTTPS、SSH 等协议的 URL。

  • <目录名> 是可选的,用于指定克隆后仓库在本地计算机上的存储位置和名称。如果不指定,Git 会使用远程仓库的名称作为目录名。

5、git fetch

用于从远程仓库获取最新的历史记录(即提交记录)

不会自动合并或修改你当前的工作。这个命令通常用于查看远程仓库的最新状态,或者在你准备合并或变基(rebase)之前,先获取最新的提交。

基本用法

git fetch [remote-name]

  • [remote-name] 是远程仓库的名称,默认是 origin。如果你没有指定远程仓库名称,Git 会尝试从默认的远程仓库(即 origin)获取数据。

常用选项
  • --all:从所有远程仓库获取数据。

  • --tags:获取所有标签(tag)的更新。默认情况下,git fetch 只会获取分支的更新,不会获取标签的更新。

  • --prune:删除那些不再存在于远程仓库中的本地引用(通常是分支和标签)。

工作原理

当你执行 git fetch 命令时,Git 会联系远程仓库,并下载你本地不存在的所有新数据(即提交、标签等)。这些数据会被保存在 .git/objects 目录下,但不会自动合并到你的工作目录或任何分支中。相反,Git 会更新你的远程跟踪分支(remote-tracking branches),这些分支以 remotes/<remote-name>/<branch-name> 的形式存在,表示远程仓库中各个分支的最新状态。

使用场景
  1. 查看远程仓库的最新状态:在合并或变基之前,先使用 git fetch 查看远程仓库的最新状态,确保你知道即将合并或变基到哪些提交。

  2. 保持本地远程跟踪分支的更新:即使你不打算立即合并或变基,也可以定期使用 git fetch 来保持本地远程跟踪分支的更新,以便在需要时能够轻松地获取到最新的远程数据。

  3. 拉取特定远程仓库的数据:如果你有多个远程仓库,并且只想从其中一个拉取数据,可以使用 git fetch <remote-name> 来指定远程仓库。

git pull 的区别

git fetchgit pull 都用于从远程仓库获取数据,但它们的行为有所不同。git fetch 只会下载远程仓库的最新数据,并更新远程跟踪分支,而不会合并或修改你的当前工作。而 git pull 实际上是 git fetchgit merge(或 git rebase,取决于你的配置)的组合,它会从远程仓库获取数据,并尝试将远程分支的最新提交合并(或变基)到你的当前分支中。因此,git pull 会改变你的工作目录和当前分支的状态。

高级功能

1、git cherry-pick

将一个或多个提交(commit)从一个分支“挑选”出来,并应用到当前分支上

git cherry-pick <commit-hash>

<commit-hash> 是你想要挑选的提交的哈希值。执行这个命令后,Git 会将这个提交应用到当前分支上,并创建一个新的提交(尽管内容相同,但哈希值会不同,因为提交上下文不同)

解决冲突

如果在挑选提交时发生冲突,Git 会暂停 cherry-pick 操作,并让你解决冲突。

解决冲突后,你需要使用 git add 命令来标记冲突已解决,

然后可以使用以下命令之一来继续或放弃 cherry-pick 操作:

继续 cherry-pick:git cherry-pick --continue

放弃 cherry-pick(并尝试恢复到原始状态):git cherry-pick --abort

注意事项
  • 这个命令用于应用一个或多个提交(commit)中所做的更改到当前分支上,但是不会将这些提交合并到目标分支的历史中。

  • git cherry-pick 会创建一个新的提交记录,新的提交记录与原始提交完全相同。

2、git submodule add

用于将另一个 Git 仓库作为子模块(submodule)添加到你的 Git 仓库中

子模块允许你将一个 Git 仓库作为另一个 Git 仓库的一个目录。这在你需要将第三方代码库或项目依赖作为项目的一部分进行管理时非常有用。

基本用法

git submodule add <repository> <path>

  • <repository> 是你想要添加为子模块的 Git 仓库的 URL。

  • <path> 是子模块仓库在你当前仓库中的路径。

示例

假设你想要将 https://github.com/example/library.git 这个仓库作为你的项目

my-project 的一个子模块,并且希望它位于 my-project/libs/library 目录下,你可以运行以下命令:

cd my-project

git submodule add https://github.com/example/library.git libs/library

执行这个命令后,Git 会做以下几件事:

  1. 在你的仓库中创建一个名为 .gitmodules 的文件(如果尚不存在),这个文件记录了子模块的信息,包括子模块的 URL 和路径。

  2. 在你指定的 <path> 下创建一个名为 .git 的目录(实际上是一个指向子模块仓库的 gitfile 或是一个裸仓库的克隆),这样 Git 就知道这个目录是一个子模块。

  3. 提交 .gitmodules 文件和你刚刚创建的空子模块目录(注意,子模块目录本身是空的,因为子模块的内容还没有被检出)。

检出子模块内容

添加子模块后,你还需要运行以下命令来检出子模块的内容到你的工作目录中:

git submodule update --init --recursive

  • --init 选项会初始化子模块配置,这通常是从 .gitmodules 文件中读取配置。

  • --recursive 选项会递归地初始化并更新仓库中的所有子模块。如果你的子模块还包含子模块,这个选项就很有用。

如果只添加了一个子模块,你也可以简单地使用 git submodule update --init 而不加 --recursive 选项。

注意
  • 子模块是 Git 仓库中的 Git 仓库。每个子模块都有自己的提交历史,你可以像操作任何 Git 仓库一样操作它们。

  • 子模块在 git clonegit pull 时不会自动更新其内容。你需要使用 git submodule update 命令来检出或更新子模块的内容。

  • 子模块可以嵌套,即你可以在子模块中再添加子模块。使用 --recursive 选项可以确保递归地更新所有子模块。

3、git stash

暂存你当前的工作进度,保存你当前的工作目录和暂存区的修改

这样做的好处是,你可以随时切换分支去处理其他事情,或者拉取最新的代码而不影响你当前的工作状态。

当你需要回到之前的工作时,你可以重新应用这些暂存的修改。

基本用法
  • git stash 暂存,保存你的工作目录和暂存区的所有修改,并回到最近的一次提交。

  • git stash save "我的工作进度" 暂存时添加一些注释

  • git stash list 查看所有已经暂存的 stash

  • git stash pop 取出最近一次暂存的修改,并尝试将它们应用到当前的工作目录和暂存区。 如果应用成功,这个 stash 就会被删除。

  • git stash show 只想查看 stash 的内容而不应用它们

  • git stash apply <stash-id> 应用特定的 stash

  • git stash drop stash@{0} 不需要某个 stash,用 git stash drop <stash-id> 命令来删除它

  • git stash clear 删除所有的 stash,

注意事项
  • 使用 git stash 时,你的工作目录和暂存区的修改会被保存,但是未跟踪的文件(即那些 Git 不知道的文件)不会被暂存。

  • 如果你在暂存了工作之后拉取了新的代码,那么在你重新应用 stash 之前,可能需要先解决合并冲突。

  • git stash 是处理多任务或避免工作被打断时的一个很好的工具,但是请注意不要过度依赖它,因为过多的 stash 可能会让你的仓库状态变得难以管理。

4、git bisect

用于帮助开发者通过二分查找法快速定位引入错误的提交(commit)

版本回退与撤销

1、git reset

用于将当前分支的头部(head)重置到指定状态

git reset [选项] [<提交>]

git reset --{soft|(mixed)|hard} HEAD

  • <提交> 是一个可选参数,指定了要重置到的目标提交。如果没有指定,则默认为 HEAD,即当前分支的最新提交。

  • --soft 其中可选参数soft表示单纯的切换HEAD指向的commit-id

  • --mixed 默认值mixed参数表示先执行上面一步,然后再将commit-id里面的内容更新到暂存区

  • --hard hard表示先执行上面两步,然后再将暂存区内容同步到工作区

git reset --hard [commit id]

用指定版本的所有文件撤回到工作区

1、git revert

用于撤销一个或多个之前的提交(commit)

git reset 不同的是,git revert 通过创建一个新的提交来“撤销”指定的提交,而不是将分支重置到某个历史状态。这意味着 git revert 不会改变项目历史中的任何现有提交,而是添加一个新的提交来“反转”之前提交所做的更改。

使用场景
  • 当你需要将某个已经推送到远程仓库的提交撤销,但又不想破坏其他人的工作或者项目的历史记录时。

  • 当你需要撤销一个合并(merge)或变基(rebase)操作,但又不想通过强制推送(force push)来重写项目历史时。

基本用法
  1. 撤销单个提交

假设你想撤销最近的提交,可以使用:

git revert HEAD

或者,如果你知道要撤销的提交的哈希值(commit hash),可以直接指定它:

git revert <commit-hash>

2、撤销多个连续提交

如果你想撤销一系列连续的提交,可以使用它们之间的范围(包含起始和结束提交):

git revert <start-commit-hash>^..<end-commit-hash>

3、撤销合并提交

撤销合并提交时,Git 会尝试创建一个新的“撤销合并”提交,该提交将“撤销”合并时引入的所有更改。但是,请注意,如果合并后的提交被进一步修改,那么简单地撤销合并可能不是最佳选择。

git revert -m 1 <merge-commit-hash>

-m 1 选项指定了要撤销的合并的“主线”(mainline),即合并时你所在的分支。如果你合并了 feature 分支到 master,并在 master 上进行合并提交,那么 1 通常表示 master 分支(即合并后的主线)。

注意
  • 撤销后的更改将成为一个新的提交,因此你需要像处理任何其他提交一样处理它(例如,推送到远程仓库)。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/953929
推荐阅读
相关标签
  

闽ICP备14008679号