Git笔记(一)——[commit, checkout]

本文详细解析了Git的基本概念,包括工作目录、暂存目录、仓库目录,并展示了如何通过各种命令进行文件的添加、提交及修改。同时介绍了commit的不同姿势,以及checkout命令在分支管理和文件恢复方面的应用。通过实例讲解,帮助读者掌握Git的高级用法,实现代码版本管理的高效操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

其实一直觉得自己是会用Git的,毕竟咱也是用Github的人啊!可是三月份找工作时候的一次面试颠覆了我的看法:

三个目录

谈到Git,最先需要明确的就是这三个概念:

  • Working Directory:工作目录,这个可以简单的理解为你在文件系统里真实看到的文件
  • Stage(Index):暂存“目录”,用git add命令添加的文件就到了这里,即将被commit的文件
  • Repository:项目“目录”,用git commit提交的文件就到了这里

后两个“目录”之所以加上引号,是因为其实它们并不是真实存在于文件系统中的目录,是个抽象的概念!为了方便后面的表述,我们就动手建立一个Git工程,并添加一个test.txt的文件。

      
1
2
3
4
      
mkdir GitNotes
cd GitNotes
git init
touch test.txt

为了更直观的观看,后续将采用SourceTree这个软件来讲解。将这个目录添加到SourceTree中可以看到:

从图1中我们可以直观的看到三个目录,其中区域1即为Repository目录,默认显示的是所有commit的log记录,由于我们还没有进行commit,所以此时看到的就是ncommitted changes。区域2的标题为Staged files,就是Stage目录,目前我们没有git add,所以这里是空的。区域3就是Working目录,与文件系统对应的,我们新建的文件test.txt就在这里,可以看到前面有个问号,表示Not Tracked,就是说这个文件从来没有被add过。

有了这些基本概念,我们来做第一次commit吧,看看文件是怎么在这三个目录下转移的吧。运行git add test.txt,观察SourceTree的面板,发现文件test.txt已经来到了区域2,如图2。运行git commit -m "add test file",文件已经到达了区域1。点击区域1的commit message,即可看到文件。标签master表示我们当前处于master分支,最新的commit为“add test file”,这个commit可以用cde6c09来唯一的标识。

commit - 我会好几种姿势呢

前面的第一次提交用的是比较常规的姿势,其实提交代码还有好多种姿势哦!我们对test.txt文件做一下简单的修改,加一行“test 1”,然后运行git commit -am "commit 1",通过加-a参数,和先运行git add .再commit的效果是一样的,也就是文件直接从Working目录到了Repo里。换个姿势再来一次,给文件加一行“test 2”,然后运行git commit test.txt -m "commit 2",这次文件也是从Working直接到Repo去了。我们还可以再换个姿势,给文件再添加一行“test 2.5”,运行git commit --amend -am "commit 2, 2.5",观察SourceTree,发现提交最后的一次提交记录被修改了,并且包含了最近的两次更改,如图3所示。

总结一下commit的几种姿势:

  1. 传统姿势:先git add filegit commit -m "xxx"
  2. 快速提交当前所有文件的更改:git commit -am "xxx"会先add所有的更改然后提交
  3. 快速提交单个文件的更改:git commit file -m "xxx"只提交这个文件的更改
  4. 修改最后一次提交:git commit --amend -am "xxx"将当前的更改加入最后一次commit中并更改最后一次commit的信息。其实观察可发现新的commit是替换了原先的commit,因为commit的hash已经变了。

关于commit还有几点想说的:

  • git commit -agit commit file这两个命令对Untracked的文件是无效了,也就是说只对add过的文件的更改才有效。比如我们新建一个文件touch test1.txt,然后运行git commit -am "add test1"git commit test1.txt -m "add test1"都是无效的,如图4所示。
  • 尽量不要使用-m标签,-m标签只适用于单行的提交信息,而提交信息最好越详细越好,方便别人,更方便自己。举个例子,给test.txt添加一行“test 3”,运行git add test.txt,再运行git commit,这时会打开Git中默认的编辑器(一般是vim),推荐像图5这样添加commit信息。其中第一行是简短的信息,第三行是详细的解释,标准就是第一行一目了然,第三行越详细越好。这样做的另一个好处是,Github默认是支持这种书写方式的,在Github的pull request里,默认显示第一行,第三行被折叠,非常方便。并且如果你的pull request只包含这一个commit的话,Github会默认将第一行作为标题,第三行作为内容,如图6。
  • 尽量也不要使用git add .git commit -a,这两条命令都会将当前所有的更改进行Stage或commit,这表面看来没什么大问题,其实是很危险的,有的时候会将未注意的更改错误的提交。Git的最佳实践还是强调小步提交,也就是说提交频繁一点,每次提交包含的更改少一点,这样不仅方便跟踪,更能避免多人合作时产生冲突。使用SourceTree这样的工具可以做到行级别的提交,也就是说一个文件我修改了好多行,可以把这些更改放到不同的commit里去。比如,修改test.txt添加两行“test 4”和“test 5”,然后打开SourceTree观察,如图7所示,点击一行后,右上角的“Stage lines”图标就会出现,这个图标的作用就是将这一行更改进行add。用这种方法,我们可以把这两行作两次提交。最终结果如图8所示。

checkout - 上得了厅堂,下得了厨房

哟哟切克闹,煎饼果子来一套!说到了吃,git checkout可以说是身兼多职——上得了厅堂,下得了厨房。一个是分支相关的操作,另一个是可以恢复文件到之前的某个状态。

平常最常用的功能就是创建和切换分支了。运行git checkout -b branch1新建一个名为“branch1”的分支并切换过去。给test.txt再添加一行“test 5.5”,做一次commit,git commit test.txt -m "commit 5.5"。这时的状态如下图:

可以看到当前的分支上有个小对号,当前所处的commit前面的圆点是白色的。此时运行git checkout master就会切回master分支。“master”这个位置不仅可以放分支的名称,还可以放commit的hash。比如git checkout cc59b55(commit 2,2.5所对应的hash),这个时候Git会给出提示信息,如下图:

此时Git处在Detached HEAD状态,从SourceTree里也可以看出有一个HEAD的tag指向对应的commit。HEAD可以理解为时一个指针,指向当前所在的分支当前的commit。其实这个时候Git处在一个“游离的匿名分支”上,Git提示说你可以做修改,做提交,但一旦你checkout到别的地方,这些提交将无法再引用到,如果你想保存,必须在此基础上创建一个新的分支。什么意思呢?我们跟着提示一步一步做。首先给test.txt文件(此时文件只有三行,最后一行是test 2.5)再添加一行“test aaa”并提交git commit test.txt -m "commit aaa"。这时,看一下SourceTree的状态图:

按照Git给的提示,此时我们checkout到别的地方去:git checkout master切回master分支,再去SourceTree看一眼,我擦泪,刚才的修改丢了!!如下图:

不听“提示”言,吃亏在眼前,难道真的像提示说的那样,刚才的修改再也找不到了吗?非也,只要记得commit的hash,我们是可以切回去,从图11中找到commit aaa所对应的hash,运行git checkout 6382c7d,再看看SourceTree,OK,都回来了!“游离的匿名分支”的取名就来源于此,这些commit目前不属于任何分支,不能通过切分支的方式找到他们,只能记住hash才能切回来。为了保存这些提交,我们按照提示新建一个分支:git checkout -b branch2。这样以后就可以通过git checkout branch2切到该分支找到这些提交了。

除了分支相关的操作,checkout的另一个作用就是恢复文件了。既然说到恢复,那肯定有source(从哪里恢复)和target(恢复到哪里去),个人感觉一般checkout的target就是指你的工作目录,而source自然是其他两个目录了。也就是说,可以从暂存目录往工作目录里恢复文件,也可以从Repo里的各个commit记录里往工作目录恢复文件。为了方便讲解,我们先切回master分支:git checkout master,然后给test.txt加一行“test temp”,这个时候可以在SourceTree里看到存在Uncommited changes,运行git checkout -- test.txt,可以看到刚才的更改被取消了,也就是说我们从Repo的最新commit里将test.txt恢复到了我们的工作目录里。这里的--符号主要是为了避免歧义,其实这里我们不要--,直接运行git checkout test.txt也是可以的,但试想这么一种情况:我们的文件名称与分支名称一样,比如有一个叫做“master”的文件,如果不加--则Git会认为你想切换分支,所以必须使用--来告诉Git你想恢复文件而不是切换分支,多才多艺的人就是这样闹心啊!我们重复同样的操作,给test.txt添加一行“test temp”并做add操作:git add test.txt,这样文件就到了暂存目录。这时候运行git checkout test.txt是没有作用的,因为你的工作目录和暂存目录是一样,继续更改test.txt,添加一行”test temp1”并保存,这里运行git checkout test.txt,则会发现新加的这一行temp1没有了,也就是暂存目录被恢复到工作目录了。实践了“Repo最新commit => 工作目录”和“暂存目录 => 工作目录”,下面试试历史commit作为source吧。为了方便,将当前暂存区的更改(“test temp”)进行提交:git commit -m "commit temp",此时的commit记录如下图:

这里我们试着将某个历史commit的test.txt恢复回来,比如将commit 3状态下对应的文件恢复,则找到对应的commit hash,运行git checkout 9fc9896 test.txt,会发现当前工作目录最后一行已经是“test 3”了,与commit 3时的文件状态一致,并且这个更改(最新的commit与commit “test 3”的差别)已经自动被add到暂存区域,如下图:

运行git reset HEAD test.txt(git add的反操作,后面会讲)和git checkout test.txt(最新的commit恢复到工作目录)来使test.txt恢复到“test temp”的状态。除了hash,还可以使用一些“快捷方式”来引用各个commit,比如刚才的操作用git checkout HEAD~3 test.txt也是一样的,其中HEAD~3表示比当前的commit早3个commit(爷爷的爸爸。。。)。说到快捷方式,其实分支名称也可以理解成一个快捷方式,代表所在分支的最新commit。比如运行git checkout branch2 test.txt,同样可以看到branch2的最新commit的状态被恢复到工作目录并添加到了暂存区。

总结一下checkout的几个功能:

  1. 分支相关操作:git checkout 分支名/commit hash切换到相应的分支或commit,加上-b参数则会创建分支并切换过去
  2. 恢复文件相关操作:git checkout [分支名/commit hash/HEAD快捷方式] -- 文件名恢复指定分支的最新commit或指定commit或快捷方式指向的commit的文件到工作目录,若省略中间的参数,则
    • 暂存区有内容且暂存区内容与工作目录不同,则恢复暂存区的状态到工作目录
    • 暂存区无内容,则恢复HEAD(最新的commit)的状态到工作目录

P.S. 本来准备把所有命令写在一篇里,不过感觉篇幅太长了也不好,这篇就到这里吧,剩下的下篇再写。

### Git 使用教程与学习笔记整理 Git个分布式版本控制系统,广泛应用于软件开发中的代码管理和团队协作。以下是关于 Git 的使用教程和学习笔记的总结,涵盖基础命令、安装方法及常用操作。 #### 1. Git 安装方法 在不同的操作系统下,Git 提供了多种安装方式: - **Linux 系统**:可以通过包管理器安装,例如在基于 Debian 的系统上使用以下命令: ```bash sudo apt-get install git ``` 如果需要从源码编译安装,则可以依次执行 `./config`、`make` 和 `sudo make install` [^2]。 - **Windows 系统**:推荐使用官方提供的安装包进行安装。此外,已安装 Git 的用户可通过以下命令更新到最新版本: ```bash git update-git-for-windows ``` #### 2. 基础命令 Git 提供了系列命令用于日常的版本控制操作: - **初始化仓库**: ```bash git init ``` 该命令用于创建个新的 Git 仓库。 - **克隆远程仓库**: ```bash git clone <仓库地址> ``` 克隆现有仓库到本地,便于后续开发和修改 [^3]。 - **查看状态**: ```bash git status ``` 显示当前工作目录的状态,包括哪些文件已被修改但尚未提交。 - **添加文件至暂存区**: ```bash git add <文件名> ``` 将指定文件添加到暂存区,准备提交。若要添加所有文件,可使用 `git add .` [^3]。 - **提交更改**: ```bash git commit -m "提交信息" ``` 将暂存区的内容提交到本地仓库,并附带条描述性的信息 [^3]。 - **推送更改至远程仓库**: ```bash git push origin <分支名> ``` 将本地提交的更改推送到远程仓库的指定分支上 [^3]。 - **拉取远程更改**: ```bash git pull origin <分支名> ``` 从远程仓库获取最新的更改并合并到本地分支中。 #### 3. 分支管理 分支管理是 Git 的核心功能之,允许开发者在同项目上并行开发多个特性或修复 bug。 - **查看分支**: ```bash git branch -v ``` 列出所有本地分支及其最新的提交记录 [^3]。 - **创建新分支**: ```bash git branch <分支名> ``` 创建个新的分支,但不会自动切换到该分支 [^3]。 - **切换分支**: ```bash git checkout <分支名> ``` 切换到指定的分支,以便在该分支上进行开发 [^3]。 - **创建并切换分支**: ```bash git checkout -b <分支名> ``` 次性完成创建新分支并切换的操作 [^3]。 - **合并分支**: ```bash git merge <分支名> ``` 将指定分支的内容合并到当前分支中 [^3]。 - **删除分支**: ```bash git branch -d <分支名> ``` 删除不再需要的分支 [^3]。 #### 4. 远程仓库操作 远程仓库通常用于团队协作,确保所有成员都能访问相同的代码库。 - **添加远程仓库**: ```bash git remote add origin <远程仓库地址> ``` 将远程仓库与本地仓库关联起来 [^3]。 - **查看远程仓库信息**: ```bash git remote -v ``` 显示所有远程仓库的详细信息 。 - **推送本地分支到远程仓库**: ```bash git push -u origin <分支名> ``` 将本地分支推送到远程仓库,并设置为默认跟踪分支 [^3]。 #### 5. 日常开发流程 在实际开发过程中,建议遵循以下步骤以保持良好的版本控制习惯: 1. 拉取远程仓库的最新代码: ```bash git pull origin main ``` 2. 添加所有修改的文件到暂存区: ```bash git add . ``` 3. 提交更改并附带清晰的提交信息: ```bash git commit -m "描述本次提交的内容" ``` 4. 推送更改到远程仓库: ```bash git push origin main ``` 通过以上流程,可以有效地管理项目的版本历史,并与其他开发者协同工作。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值