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工作流,和开源作者们使用同一套流程

相关推荐
San813_LDD几秒前
[深度学习]量化研究_ML_Lesson2
笔记
数智工坊1 分钟前
周志华《Machine Learning》学习笔记--第十六章--强化学习
笔记·学习·机器学习
ChindongX8 分钟前
笔记:解决窗口透明度不生效问题 —— QGraphicsOpacityEffect 的使用
笔记·qt
知南x10 分钟前
【DPDK例程学习】(1) helloworld
学习·word
Sc Turing13 分钟前
【AI学习0611】
学习
GHL28427109013 分钟前
Trae学习
学习
一锅炖出任易仙13 分钟前
创梦汤锅学习日记day31
学习·ai
木雷双雄715 分钟前
Git 版本回退操作指南
git
aaaameliaaa26 分钟前
分支与循环
c语言·笔记
MartinYeung527 分钟前
[论文学习]DP 微调 LLM 隐私防护实证研究:方法比较与洞见
网络·学习