Git学习自用笔记

1. 初始化仓库

初始化仓库有两种方式。一种是直接在本地构建,另外一种是克隆远程仓库。

  1. 本地构建:git init [本地仓库路径]
  2. 克隆远程仓库:git clone <仓库地址>

2. 工作区域和文件状态

2.1 三种工作区域

  1. 工作区(Working Directory),其实就是我们所在的工作目录;
  2. 暂存区(Staging Area/Index),用于临时存在我们即将提交到本地仓库的内容:.git/index
  3. 本地仓库(Local Repository),是存储代码和版本信息的主要区域:.git/objects

2.2 四种文件状态

  1. 未跟踪(Untrack),指该文件还未被git管理起来;
  2. 未修改(Unmodified),指该文件已经被git管理起来,自首次提交后还未被修改过;
  3. 已修改(Modified),文件被git管理且被修改过,但还没提交到暂存区;
  4. 已暂存(Staged),指文件已经保存到了暂存区;

在Vscode中,使用如下缩写对应文件状态:

  1. ??(Untracked):未追踪
  2. 不显示:未修改
  3. M(Modified):已修改
  4. A(Added):已添加暂存
  5. D(Deleted):已删除
  6. R(Renamed):重命名
  7. U(Updated):已更新未合并

可以看到,状态5、6和7是比较特殊的。5和6可以视为是已修改的特殊情况,而7则是在合并冲突时显示。当然有时U也会被用作U(Untracked);

2.3 二者的交互

  • 文件初始状态:Untracked
  • 命令git add将文件添加到暂存区,状态变成Staged
  • 命令git commit将暂存区的文件提交到本地仓库,状态变成到Unmodified
  • 提交过后的文件经过一次修改,状态变成Modified

总结来看,Untracked是未被git add过的文件的初始状态;Unmodified是被git commit后的初始状态。

3. 内容添加与提交

3.1 添加到暂存区

  • git add <filename>将文件添加到暂存区。示例:
    git add A.py # 添加具体文件 git add *.txt # 使用通配符添加文件 git add . # 使用相对路径添加文件夹(当前文件夹所有文件)
  • git rm <filename>将文件从工作区和暂存区同步删除掉,避免手动删除本地文件后再用命令去同步暂存区的内容。等价于手动删除本地文件后,再使用git add 被删除文件
  • git restore <filename>取消指定文件的暂存状态。

3.2 提交到本地仓库

使用git commit将暂存区的内容提交到本地仓库,其中:

  • 使用-m参数,如git commit -m "first commit"
  • 无参数默认进入Vim编辑界面以编辑提交信息。敲击ESC键,显示:后输入wq退出界面;
  • 使用-am参数,其中a表示git add .,即将当前工作区内容添加到暂存区,再将暂存区内容提交到本地仓库。

3.3 查看

  • git ls-files查看被Git管理的文件,可以使用-m查看已修改但未暂存的文件;
  • git status查看工作区和暂存区文件状态
  • git log查看仓库提交历史记录,可以使用--oneline参数来查看简洁的提交记录。
  • git reflog,查看过去所有使仓库发生变化git变化

!Note\] 有些文档说 `git ls-files --cached`可以查看暂存区文件情况,实践证明这完全是扯淡。标准做法是使用 `git status`查看暂存区的情况。

4. 版本回退

4.1 内容回退

使用git reset进行版本回退。它有三种默认参数:

  1. git reset --soft表示回退后保留当前工作区和暂存区的所有内容
  2. git reset --hard表示回退后丢弃当前工作区和暂存区的所有内容
  3. git reset --mixed表示回退后保留当前工作区的内容,但是丢弃暂存区的所有内容。默认使用该模式。

特殊符号:HEAD^表示上一个版本,例如:

复制代码
git reset HEAD^

配合git log --oneline命令可以方便回到某一个版本的提交;如果发生误操作,可以使用git reflog查看具体的失误操作id并回退;

5. 差异比较

git diff可以用于查看不同工作区、暂存区和本地仓库、不同版本以及不同分支之间的差异。

  1. 不加任何参数,git diff默认比较工作区与暂存区之间的差异。
  2. git diff HEAD比较工作区和本地仓库(最新提交)之间的差异;
  3. git diff --cached比较暂存区和本地仓库的差异;
  4. git diff id1 id2是比较不同版本或分支的通用写法,表示比较id2相对id1的变化。

特别的,我们常用HEAD指代特定版本。它的用法是:

  • HEAD表示当前版本
  • HEAD~HEAD^表示前一个版本
  • HEAD~3表示前3个版本

例如下述常见的命令,表示当前版本相对上一个版本的变化:

复制代码
git diff HEAD~ HEAD

6. 忽略文件

显然我们不希望某些文件被Git管理,如临时文件,缓存等等。此时我们可以使用.gitignore文件,在里面列出这些文件或文件夹,匹配规则是标准的glob正则表达式;注意文件夹必须以/结尾,如config/;常见模版见:gitignore模版

特别的,如果某些不想被管理的文件已经被Git管理起来,我们希望将其从暂存区删除,可以使用如下命令:

  • git rm --cached 文件名
  • git rm --cached -r 文件夹名

特别注意,--cached表示只是删除暂存区的对应文件内容;-r表示recursively递归,即递推删除指定文件夹下所有文件。

7. 同步本地仓库和远程仓库

7.1 仓库关联

  1. 如果仓库是git clone下来的,那么这个克隆下来的本地仓库和远程仓库已经有了关联;
  2. 如果仓库是git init创建的,并且需要与远程仓库建立关联,则使用如下命令。例如: git remote add <仓库别名> <仓库链接>

可以使用如下命令可以查看本地仓库锁关联的远程仓库信息:

复制代码
git remote -v

7.2 信息同步

  1. git pull表示拉取,即将远程仓库的修改拉取到本地,完整命令如下: git pull <-u 远程仓库名> <远程分支名>:<本地分支名>
  2. git push表示推送,即将本地仓库的修改推送到远程仓库,完整命令如下: git push <远程仓库名> <本地分支名>:<远程分支名>

这两个命令都可以进一步添加其他参数。例如下述命令表示将本地仓库与远程别名为origin的仓库连接,并把本地仓库main分支的内容推送到远程仓库的main分支:

复制代码
git push -u origin main:main

8. 分支

8.1 基本命令

  1. 查看当前仓库的所有分支:git branch
  2. 创建新分支:git branch <分支名>
  3. 切换分支:git switch <目标分支>
  4. 合并分支:git merge <目标分支>git rebase <目标分支>
  5. 查看分支图:git log --graph --oneline --decorate --all
  6. 删除已合并的分支:git branch -d <目标分支>
  7. 强制删除分支:git branch -D <目标分支>

!NOTE

  1. 虽然也可以用git checkout <分支名>来切换分支,但这种方式是有歧义的。因为是git checkout XX的还可以用来恢复某个文件的意外修改。如果某一个文件的名字恰好和分支名相同,git checkout XX会优先选择切换到对应的分支而不是恢复文件,从而导致歧义。
  2. git merge表示将目标分支合并到当前分支中。因此如果想将开发功能分支合并到主分支中,记得先切换回主分支,再执行merge命令。
  3. 合并分支后,目标分支并不会消失。如果确定被合并的分支不再需要了,可以使用第6条命令删除对应分支。

8.2 两种分支合并的方式

git mergegit rebase是合并分支的两种不同的方式。假设我们的主分支是main,开发分支是dev;如果我们想将dev分支合并到main分支的话:

  1. git switch main;git merge dev在将dev分支内容合并后,只会在main分支上产生一个新的merge提交,不会破坏原有的分支结构。
  2. git switch main;git rebase dev在将dev分支内容合并后,会将main分支的提交历史和dev分支嫁接,具体解释是:
  • rebase意为"变基","基"意为共同的祖先。假设dev分支是在main第三次提交时创建的,那么第三次提交就是两个分支的共同祖先;
  • 命令会将main分支第三次提交后的内容移动到dev分支的最新提交后面,相当于把main的共同祖先从第三次提交变成了dev的最新提交;
  • 这样main分支中有了dev分支的完整提交历史;缺点是,这种方式破坏了main分支的实际提交顺序,也破坏了原有的分支结构。git switch dev;git rebase main同理;

在实际开发中,git merge则适合团队开发写作,避免破坏原有的分支结构和提交历史;git rebase则适合个人开发项目使用,可以将不同分支的提交历史合并成一条清晰的脉络;

9. 开发的工作流程

理解至上!详见视频: 十分钟学会正确的github工作流,和开源作者们使用同一套流程

相关推荐
程序员小崔日记3 小时前
如何将代码轻松上传到 Gitee?Git 使用全攻略!
git·gitee·上传
Bigger1 天前
为什么你的 Git 提交需要签名?—— Git Commit Signing 完全指南
git·开源·github
DianSan_ERP2 天前
电商API接口全链路监控:构建坚不可摧的线上运维防线
大数据·运维·网络·人工智能·git·servlet
西岸行者2 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
starlaky2 天前
Django入门笔记
笔记·django
勇气要爆发2 天前
吴恩达《LangChain LLM 应用开发精读笔记》1-Introduction_介绍
笔记·langchain·吴恩达
悠哉悠哉愿意2 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
勇气要爆发2 天前
吴恩达《LangChain LLM 应用开发精读笔记》2-Models, Prompts and Parsers 模型、提示和解析器
android·笔记·langchain
别催小唐敲代码2 天前
嵌入式学习路线
学习