30

Git 学习手册(常见问题整理)

Git 是一个分布式版本控制系统,提供了高效的代码管理和协作功能。本文将整理一些常见的 Git 问题及其解决方案。

我们经常会遇到多人合作开发的项目,但是问题是,当我们多个人共同开发一个项目时,怎么把大家的合起来呢?

串行工作:每个人负责一个模块,在这个人书写自己的模块时,其他人闲着,在这个人写好代码后,把代码打包,压缩包发送给下一个人。 并行工作:多人同时进行编码,写好之后进行合并。

你平时是怎么操作的呢?实际上,显然是并行工作的效率高,但是怎么达到这个目的呢?答案就是,代码托管。我们将代码放在某个平台的仓库里上,每个协作者在仓库中创建一个属于自己的分支(branch),并将代码拷贝一份副本在本地,在本地进行自己部分的编码和测试工作,在编码完成后,把这个工程推送(Push)到仓库中自己的分支里,并向主分支(main)发起合并请求(pull request),在管理员审核过后,就可以自动比较二者不一样的地方,进行合并(Merge)。

比如,老师新出了一张试卷,但是老师不想自己得到答案,因此她安排A、B、C三位学霸来做这套试卷。分别将这三个同学的试卷记为a、b、c。假设老师那里有一张空白试卷m。那么老师就是一个仓库。这张试卷m就是主分支(branch main),试卷a、b、c就是另外三个子分支。老师安排A同学做选择题,B同学做填空题,C做大题,在A做完选择题后,他将卷子交给老师(这叫提交合并请求),老师看了之后觉得没问题,就把A的答案誊抄到空白卷m上(这叫合并),B做完填空题后,手比较痒,就另外做了选择题,他也把卷子交给老师,老师看了之后,发现B的选择题答案和A的不一样(这叫产生了冲突),老师经过仔细判断之后发现A写的是对的,就保留A的选择题答案,忽略B的选择题答案(这叫解决冲突),然后将B的填空题合并上去。C做完大题之后交给老师,老师经过审核发现没有冲突的地方,因此也把C的试卷合并到m中。

Git 的诞生(了解)

在 2000 年代初,Linux 内核是世界上最大和最复杂的开源项目之一。为了协同开发,Linux 社区当时使用一个叫 BitKeeper 的分布式版本控制系统(DVCS)。BitKeeper 由商业公司 BitMover 开发,对 Linux 社区开放免费使用,但有严格的授权限制。

到了 2005 年,BitMover 公司认为一些开发者违反了协议(如试图逆向工程),于是撤回了对 Linux 社区的免费使用授权。这一下子让 Linux 社区陷入了危机:

为了应对这一危机,Linux 的创始人 Linus Torvalds 决定自己使用 C 语言开发一个新的版本控制系统。这就是 Git。目标很明确:

  • 分布式(每个开发者都有完整的历史)

  • 高性能(特别是对大型项目)

  • 数据完整性强(使用 SHA-1 哈希验证)

  • 支持非线性开发(如分支和合并)

Git 的第一次发布是在 2005 年 4 月。

从那以后,Git 不断发展,成为世界上最流行的版本控制系统。

集中式和分布式版本控制系统的区别

  • 集中式版本控制系统(如 SVN),版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟。

  • 分布式版本控制(如 Git),每个开发者本地都有完整的仓库,包含代码和完整的历史。本地即可完成提交、查看历史、创建分支等操作。与远程仓库同步是可选的,通常用来协作。可以离线工作。

什么是工作区、暂存区和版本库?

在使用 Git 的过程中,我们经常接触到三个区域:工作区、暂存区和版本库。简单来说,它们分别代表了代码在不同阶段的位置。

工作区就是我们平常写代码的地方,也就是你在电脑上能直接看到和编辑的文件夹。我们所有的修改,最开始都是发生在工作区。

暂存区可以理解为一个准备提交的区域。当你写完代码,觉得可以提交一部分改动时,会先用 git add 命令把这些改动放到暂存区。这个时候改动就从“修改中”变成了“准备好提交”的状态,但还没有真正记录到 Git 的历史中。

版本库(也叫本地仓库)是 Git 真正用来保存项目历史的地方。当你执行 git commit 的时候,其实就是把暂存区的内容记录到版本库里,从而形成一个快照,这个快照就可以一直被追踪、回退或者分享给其他人。

所以整个流程其实就是:我们先在工作区写代码,写完之后用 git add 把它们加入暂存区,然后再通过 git commit 把这些改动保存到版本库里。如果之后要推送给团队其他人看,再用 git push 把本地版本库同步到远程仓库。

🌟 git add、git commit、git push 的作用分别是什么?

git add 的意思是: 👉 “我修改好了这些文件,准备让 Git 跟踪并提交它们。”

它不会直接提交,只是把你改动过的文件放到一个“准备提交”的区域,也就是暂存区(staging area)。你可以选择一次只添加一个文件,也可以添加所有改动。

git add main.py
## 或者提交所有文件到暂存区
git add .

git commit 的意思是: 👉 “把我刚才准备好的那些改动正式记录下来。”

这个命令会把暂存区里的所有内容,打包成一个新的提交(也叫一个快照),写入到版本库中。这就是 Git 的“记一次账”。你通常会配上一条说明这个提交的日志,比如:

git commit -m "修复了登录功能的 bug"

每次提交后,你的项目历史就多了一个版本,你可以随时回到它。

git push 的意思是: 👉 “我已经在本地提交好了,现在把这些提交同步到远程仓库去。”

比如你想把改动推送到 GitHub 上的某个项目,就执行:git push origin main这里的 origin 是远程仓库的名字,main 是你要推送的分支。这样其他人就可以看到你最新的提交了。

🌟 解释 Git 中的 HEAD 指针是什么

HEAD 指向你当前检出的分支的最新一次提交(也叫最新的 commit)。你可以把它想成是 Git 的“当前状态指针”,它告诉 Git:“现在我正处于哪个分支的哪个提交上”。

比如说,当你在 main 分支工作时,HEAD 实际上是指向 main 这个分支,而 main 又指向这个分支上的最新一次提交。如果你做了新的提交,那么 main 会向前移动到新的提交,HEAD 也会随着一起移动。

有时候我们会进入一种叫“分离 HEAD”(detached HEAD)的状态。这通常发生在你直接检出了一个具体的提交(比如 git checkout abc1234),而不是一个分支名。这个时候 HEAD 就不再指向某个分支了,而是直接指向某个提交。你可以修改代码、提交新内容,但这些改动不会附加在任何分支上,除非你手动创建一个新的分支来保存它们。

什么是 Git 仓库(repository)?

Git 仓库,也就是 repository,简单来说就是用来存放你项目的整个版本历史的地方。

当你用 git init 创建一个新的仓库时,Git 会在你的项目目录下生成一个隐藏的 .git 文件夹。这个文件夹就是 Git 仓库的核心所在,里面包含了所有的提交历史、分支信息、标签、配置。

这个仓库可以是本地的,也可以是远程的。

如何初始化一个 Git 仓库?

假如你已经有一个项目文件夹了,只需进入这个文件夹,然后运行 git init

这个命令会在当前目录下创建一个隐藏的 .git 文件夹,这个文件夹就是 Git 的核心仓库,它会负责记录你项目中的所有提交历史、分支信息、配置等等。

如何查看当前仓库的状态?如何查看提交历史?

可以找一个仓库修改一两个文件试一试

git status 这个命令会告诉你当前仓库的整体状态,比如:

  • 哪些文件被修改了但还没有 add 到暂存区

  • 哪些文件已经被 add 到暂存区,准备提交

  • 有没有未跟踪(untracked)的新文件

  • 当前你所在的分支名称

  • 有没有改动还没提交,或者提交还没推送

git log 它会显示当前分支的提交历史,每个提交包括:

  • 提交的哈希值(commit ID)

  • 作者是谁

  • 提交时间

  • 提交说明(commit message)

🌟 如何撤销工作区的修改?

如果只是改动了文件,还没 add 到暂存区,可以使用 git restore FILENAME 来重置修改的某个文件。或者使用 git restore . 来重置整个工作区。

🌟 如何撤销已经 add 但未 commit 的修改?

这时你想撤销暂存区的状态,可以用:

git restore --staged 文件名

这个命令的意思是:“别把这个文件放在暂存区了”,它会把文件从暂存区移回工作区,等于取消了 git add 的效果。

你可以接着用上面的 git restore 文件名 来撤销实际修改。

🌟 如何撤销已经 commit 的修改?

有四种情况:

  • 刚刚 commit,还没 push,只是想改提交信息,不想修改文件

使用 git commit --amend,这个命令会打开一个默认的文本编辑器,让你修改写的 commit 的内容。(amend 有修改的意思)

  • 想撤销刚刚的 commit,让改动回到暂存区

使用 git reset --soft HEAD~1 取消最近一次提交,但保留所有修改在暂存区,你可以重新提交、修改、拆分等。(soft 温和地回退)

  • 想撤销 commit,让代码回到工作区

使用 git reset --mixed HEAD~1 这样不仅取消了提交,也把文件从暂存区移回工作区(但不会删代码,只是让你重新处理)。(mixed:介于 hard 和 soft 的中间态)

  • 想完全抹掉 commit 和代码改动,一切都清零

git reset --hard HEAD~1,这个会把代码、暂存区、提交统统回滚到上一次提交的状态。本地修改会被彻底清除,不能恢复。

🌟 如何撤销已经 Push 的修改?

可以先在本地使用上面的一系列 reset 指令撤销到想要撤销的程度。然后用 git push --force 强制更新远程仓库。这个过程就像是在告诉 Git:“我后悔了,我要重写历史”,而 --force 是一个强制让远程仓库接受这个“改历史”的操作。

但如果这个提交已经被其他人拉取或基于它写了新的内容,这样的强推就会造成别人的历史混乱,可能让他们的代码出错或者无法推送。

所以如果你是在一个多人协作的项目中,建议不要随便用 git reset 和强推,而是用 git revert

🌟 说说 git revert?和 reset 的区别?

它的作用是“反做一次提交”,也就是说,它会创建一个新的提交,这个提交的作用就是“把之前那个提交做的事反过来”。 比如你上次提交了一个文件修改,现在发现有问题,你可以用 git revert 把它撤销,Git 会自动生成一个新的提交,让你的代码状态回到修改前。

git revert <commit-id> -m "撤回错误提交"

这个过程不会改动提交历史,历史记录仍然是连续和完整的,只是新增了一个“纠正用”的提交。Head 指针还是向前移动的。

而 git reset 它直接把 Git 的 HEAD 指针往回移动,回到你指定的旧提交上。

什么是 Git 分支?为什么要使用分支?

Git 分支可以理解为一种并行开发的方式。它允许你在不影响主线代码的前提下,开辟一个新的开发轨道,做实验、修 bug、开发新功能,然后再把成果合并回主分支。

我们通常把 mainmaster 分支当作“发布用”的主分支。用分支开发新功能或修复 bug,可以保证主分支始终保持稳定状态,避免直接在主线上动手带来风险。

并且多个人进行开发可以在不同的分支上进行,大家互不干扰,做完后合并到一起即可。

K8S 的分支管理

🌟 如何创建、切换、删除分支?

创建分支只需要 git branch 分支名,这个命令就会在你当前所在的提交位置(通常是主分支)上创建一个新的分支。

如果想要切换到某个分支可以:git checkout 分支名,也可以使用新版的方法 git switch 分支名

删除分支,git branch -d 分支名,这个 -d(小写)表示安全删除,如果该分支已经被合并到主分支,就会删除成功;如果没有合并,Git 会阻止你删,避免你误删了未保存的改动。如果想要强制删除可以用 git branch -D 分支名

🌟 如何合并分支?

一般情况下我们都使用 git merge 合并分支。

首先切换到想要合并进去的分支,例如 main 分支。git checkout main,然后执行合并命令 git merge feature/login,将分支合并到 main 分支中。

如果两个分支没有冲突,Git 就会直接生成一个新的合并提交,表示“这两个版本现在合并到一起了”。如果 Git 检测到冲突,比如两个分支都改了同一个地方,它就会提醒你冲突了,需要你手动打开文件,把冲突的部分解决掉。解决完后再 git add . 和 git commit。

🌟 如何使用 git rebase 合并分支?

git rebase 命令的文档描述是 Reapply commits on top of another base tip,从字面上理解是「在另一个基端之上重新应用提交」,这个定义听起来有点抽象,换个角度可以理解为「将分支的基础从一个提交改成另一个提交,使其看起来就像是从另一个提交中创建了分支一样」,如下图:

假设我们从 Master 的提交 A 创建了 Feature 分支进行新的功能开发,这时 A 就是 Feature 的基端。接着 Matser 新增了两个提交 B 和 C, Feature 新增了两个提交 D 和 E。现在我们出于某种原因,比如新功能的开发依赖 B、C 提交,需要将 Master 的两个新提交整合到 Feature 分支,为了保持提交历史的整洁,我们可以切换到 Feature 分支执行 rebase 操作:

git rebase master

rebase 的执行过程是首先找到这两个分支(即当前分支 Featurerebase 操作的目标基底分支 Master) 的最近共同祖先提交 A,然后对比当前分支相对于该祖先提交的历次提交(D 和 E),提取相应的修改并存为临时文件,然后将当前分支指向目标基底 Master 所指向的提交 C, 最后以此作为新的基端将之前另存为临时文件的修改依序应用。

我们也可以按上文理解成将 Feature 分支的基础从提交 A 改成了提交 C,看起来就像是从提交 C 创建了该分支,并提交了 D 和 E。但实际上这只是「看起来」,在内部 Git 复制了提交 D 和 E 的内容,创建新的提交 D' 和 E' 并将其应用到特定基础上(A→B→C)。尽管新的 Feature 分支和之前看起来是一样的,但它是由全新的提交组成的。

(参考了 https://waynerv.com/posts/git-rebase-intro/)

git rebase 和 git merge 的区别

  • git merge 的做法是:把两个分支的历史保留下来,然后创建一个新的“合并提交”来把它们连接在一起。这样做不会改历史,比较安全,也适合多人协作。就像两条河流汇合在一起,会留下“汇合点”的痕迹。

  • git rebase 的做法是:把你当前分支的提交“剪下来”,然后一个个地重新应用到目标分支的末尾,让整个历史看起来就像你一直在那条主线上开发一样。不会有“分叉”和“合并”的痕迹,历史更线性。就像你把旁边那条支流里的水重新倒进主河道,不留分支的痕迹。

什么是快进合并(fast-forward)?

快进合并,也叫 fast-forward 合并,是 Git 在合并分支时的一种特殊情况,它发生在你的主分支没有任何新的提交,而你要合并的那个分支是在主分支的基础上继续向前推进的

这个时候,Git 发现主分支其实可以直接“快进”到目标分支的位置,根本不需要生成一个新的合并提交。

假设现在你的 main 分支有三个提交:A → B → C 你从 C 开了一个新分支 feature,在上面又做了两个提交:D 和 E

当你需要合并的时候 Git 会发现:main 没变过,只要把它快进到 E 就行了,连个合并节点都不用创建。

🌟 如何解决合并冲突?

当我们在 Git 里合并分支时,如果两个分支修改了同一个文件的同一部分,Git 就没办法自动决定该保留哪一块内容,这时候就会发生合并冲突。

如果有冲突,Git 会直接告诉我哪些文件有问题。然后我会打开这些冲突的文件,Git 已经把冲突的部分用特殊的标记标出来了,比如:

<<<<<<< HEAD
这是当前分支的内容
=======
这是合并进来的内容
>>>>>>> feature

我需要手动判断保留哪一部分,或者干脆自己重新改一段。处理完这些文件后,保存并退出。然后 add 和 commit 一次即可。

🌟 什么是分支策略?常见的分支策略有哪些?

分支策略,其实就是团队在开发过程中如何管理和使用 Git 分支的一套规则。它的核心目的是让多人协作更有条理、代码更稳定、发布更可控。就像在高速公路上开车要有规则一样,代码的分支管理也需要明确谁在哪条“道”上跑,什么时候合并,怎么发布。

常见的策略有:

  • Git Flow,为不同阶段的工作分不同的分支,比如:

    • main 是线上发布用的稳定分支

    • develop 是日常开发分支,所有功能分支从这里拉

    • feature/* 用于开发新功能

    • release/* 用于准备版本上线前的最后整理

    • hotfix/* 用于紧急修复线上 bug

  • GitHub Flow

    • 所有人从 main 拉分支(比如 feature/xxx

    • 每个分支对应一个功能或修复

    • 开发完成后提交 Pull Request(合并请求)

    • 通过代码审核和自动测试后合并回 main

    • 合并后可以立即上线

🌟 git fetch 和 git pull 的区别是什么?

  • git fetch 就像是你去远程仓库“打听消息”,把别人最新的提交下载回来,但不会自动合并到你当前的分支。你只是把这些更新暂时放在本地的一个“远程分支”里,需要你自己手动决定要不要合并、怎么合并。

  • git pull 是“打听消息 + 自动合并”两步合在一起。内部实际上就是 git fetch + git merge。执行 git pull 会直接把远程分支的更新拉下来,然后合并进你当前所在的分支,有可能导致冲突,或者影响你本地的代码状态。

什么是 git diff 指令?

git diff 是 Git 里用来比较差异的命令,它可以帮我查看两个版本之间的代码改动,也可以用来对比当前工作区和暂存区的区别。

例如 vscode 就自带这个功能:

🌟 如何添加远程仓库?

如果在本地创建 git 仓库的时候,是没有同步远程仓库的,添加远程仓库其实就像是告诉 Git:“我这个项目对应的远程版本放在哪儿,以后可以同步更新。”

git remote add origin 仓库地址(比如 https://github.com/username/project.git)

什么是上游分支(upstream)?

上游分支,其实就是当前分支默认关联的远程分支

比如我在本地有一个 main 分支,它是从远程的 origin/main 拉下来的。Git 会自动把 origin/main 设置为本地 main 的上游分支。这样我在 main 分支上执行 git pullgit push 时,就不需要每次都写完整的远程地址和分支名,Git 会自动知道我要同步的是哪个远程分支。

除了 Git 自动设置,我也可以手动指定上游分支,比如:

git branch --set-upstream-to=origin/dev dev

这个命令的意思是:让本地的 dev 分支跟远程的 origin/dev 分支关联起来。

如何强制推送?什么情况下需要强制推送?

强制推送就是用 git push --force 或简写 git push -f,它的作用是:把本地的分支历史强行覆盖远程分支的历史,不管远程那边有没有冲突或者是否落后。

在什么情况下需要强制推送?最典型的场景是我在本地使用了 git rebasegit reset 改写了提交历史,然后要把这段“新历史”推送到远程。如果不用 --force,Git 会阻止你推送,因为它检测到你的历史和远程分支不一致,这样可以防止误覆盖别人的代码。

🌟 什么是 git stash?如何使用?

git stash 是 Git 提供的一个临时“藏东西”的工具。它的作用是:把当前工作区的修改暂时保存起来,然后把代码恢复到干净的状态,方便我去切换分支、拉代码或者做其他操作,等有空了再把改动拿回来继续处理。

我平时会在这种情况下用它:比如我正在开发一个功能,改到一半突然有个紧急 bug 要修,得切到另一个分支处理。但现在的代码还没写完也不能提交,这时候我就可以执行:

git stash

这条命令会把当前所有未提交的修改(包括还没 add 的)存到一个“栈”里,然后把工作区恢复到上一次提交的状态。

等我修完 bug,切回原来的分支,想继续开发时,只需要:

git stash pop

如何使用 git cherry-pick?

git cherry-pick 是一个用来“挑选提交”的命令。它的作用是:把其他分支上的某一次(或几次)提交,单独拿过来,应用到我当前的分支上,而不是整个分支都合并。

我会在这种场景下使用它:比如我在 feature/login 分支上修了一个 bug,提交了,但现在产品紧急希望这个修复也出现在 main 上,但又不想把整个 feature/login 的其它开发内容合进来。这时候我就可以用 cherry-pick 把那一次 bug 修复的提交“挑出来”放到 main

git switch main
git cherry-pick abc1234

这里的 abc1234 是那次提交的哈希值。

什么是 git reflog?什么时候会用到?

git reflog 是 Git 的一个“内部日志”,它记录了所有你对 HEAD 和分支指针做过的操作,不管你有没有提交。这些记录包括你切换分支、合并、rebase、reset、甚至 commit 的移动,Git 都会记下来。

这个命令在正常开发时可能不会经常用到,但在你“出事”的时候非常有用。比如:

  • 我不小心用 git reset --hard 把代码回滚了

  • 或者我执行了 rebase,改写了历史,结果发现原来的内容丢了

  • 又或者我误删了一个分支,但里面有我想要找回的提交

这些情况下,我就可以用:

git reflog

Git 会列出一串像这样的记录:

abc1234 HEAD@{0}: reset: moving to HEAD~1
def5678 HEAD@{1}: commit: 修复登录逻辑
...

每一行都代表一次 HEAD 的变动,我可以从中找到想要恢复的那个 commit,比如:

git checkout HEAD@{2}

如何修改提交信息?

如果还没有 push,可以使用 git commit --amend 修改最新的那个提交的信息。

但是如果我要修改的是历史中的某一条提交(不是最新的),那就需要用到:

git rebase -i HEAD~N(例如 N = 3)

这个命令会列出最近 3 次提交的列表,我可以在想修改的那一行前面把 pick 改成 reword,然后 Git 会让我修改那条提交的信息。操作完成后,它也会重写那部分历史。

如果已经 PUSH 了,因为 rebase 或 amend 都是改历史,一旦你推送这些改动回远程,就必须使用 --force。这可能会影响其他协作者的历史,导致冲突或推送失败。所以在这种情况下,我会先判断这是不是自己的个人分支,如果是,可以用 --force 推送。如果是公共分支,我更倾向于不要动历史,而是新提交一条说明,比如“修正前一条提交说明”,这样更安全,也更尊重团队协作。

🌟🌟 描述一个典型的 Git 工作流程

平时工作中,我一般是先从主分支拉取最新代码,确保本地是最新的,然后基于主分支创建一个新的功能分支,比如 feature/login。

接下来我会在这个功能分支上进行开发,修改代码之后,用 git add 把改动的文件加入暂存区,然后用 git commit 提交。

开发完成之后,我会先拉一下主分支的最新更新,合并进我的分支来解决可能的冲突。确保没问题之后,就把我的分支推到远程,然后发起一个合并请求,让团队成员做 code review。等代码审核通过,我就把分支合并进主分支。

🌟 如何进行代码审查(Pull Request/Merge Request)?

在实际项目中,我们通常使用 GitHub、GitLab 或 Gitee 这类平台来进行代码审查,也就是通过 Pull Request(GitHub)来完成。

当一个开发者完成了某个功能后,先把代码推送到远程仓库的一个独立分支,然后发起一个 PR 或 MR,请求将这段改动合并到主分支或者开发分支。

审查流程一般是这样:

首先团队成员会收到通知,进入审查页面,查看改动的文件。我们会重点关注几个方面:

  • 一是代码逻辑是否正确,是否符合需求;

  • 二是编码规范,比如变量命名、缩进、注释是否清晰;

  • 三是有没有重复代码或者可以优化的地方;

  • 四是有没有遗漏测试,或者可能引入隐患的地方;

  • 五是和已有功能有没有冲突,特别是对公共模块的改动。

如果发现问题,我会在具体行上直接评论,提出修改建议,或者发起讨论。如果没问题,就会给出通过的标记,比如 Approve。

开发者根据审查意见修改代码后再推送一次,PR 会自动更新。直到所有审查人通过后,代码就可以被合并到目标分支中。

查看一个典型的 Pull Request 示例(来自 k8s):https://github.com/kubernetes/kubernetes/pull/131984

🌟 如何恢复被删除的分支或提交?

在实际工作中,有时候我们会不小心删掉一个分支,或者 reset、rebase 之后发现某些提交没了。这个时候可以使用 git reflog

Git 的 reflog 记录了所有分支和 HEAD 的移动历史,哪怕我把分支删了,只要这些操作还没被垃圾回收,Git 其实都知道我做过什么。比如:

我不小心删除了本地的 feature/login 分支,但记得它之前是从某次提交分出去的,我就可以用 git reflog 查看最近的提交移动记录。找到那次提交的哈希值之后,只要执行:

git checkout -b feature/login <哈希值>

就能重新建立这个分支,指向原来的提交。

如何查看文件的修改历史?

git log 文件名这个命令会列出所有对这个文件有过改动的提交记录,按时间倒序排列。它会显示每次是谁改的、什么时候改的、提交说明是什么。

push 失败时可能的原因和解决方法?

  • 最常见的一种是:远程分支比我本地更新了,我 push 的内容会导致冲突。可以先 Pull 一下,解决完冲突再发起 Push。

  • 网络问题,要使用魔法才能连上 GitHub

  • GitHub 的 Token 填错了,或者登录错了用户。

如何配置 Git 用户信息?

在使用 Git 之前,最基础的一步就是配置用户信息,也就是告诉 Git:“我是谁”。主要是两个字段:用户名(user.name)和邮箱(user.email),因为每次提交时 Git 都会把它们写进提交历史中。

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

加上 --global 的意思是,这个配置会对你电脑上所有的 Git 仓库生效。如果我只想对某一个项目单独设置,也可以去掉 --global,Git 会只在当前仓库里保存这组信息。

什么是 .gitignore 文件?如何使用?

.gitignore 是一个告诉 Git:“有哪些文件你别管,不用跟踪、不用提交”的配置文件。

它的作用是忽略那些不需要进入版本控制的文件,比如临时文件、日志、编译生成的二进制文件、操作系统自动生成的文件,或者开发工具自动生成的缓存。