四个指令玩转github

一. 前言

我先开一会儿吐槽大会,从大四进课题组做科研开始,Git 这东西我用了一年,根本用不明白。

我搞不明白的一个重要原因就是,命令的功能太杂,有时候一个需求可以用好几种命令解决,而且有的命令还 tm 有别名。这导致什么问题呢,我在网上找到的答案五花八门,竟然都能达成目的,难以找到规律,毫无套路可言。
以前我用 Git,就知道 add .,然后 commit -m,最后 push origin master 一套带走,或者就是把 Git 作为下载器,去 clone 别人的项目。可是在日常项目使用过程中经常遇到因为手残把代码弄错了需要恢复到原来的版本的问题,对于git的学习,我的经验是,一是投入实践,二是化复杂为简单。
所以本文不是一个大而全 Git 命令的使用手册,而是根据实际工作中最常见问题,提供小而美的解决方案,仅仅涉及四个命令:add,commit,reset,checkout。
远程仓库涉及的三个命令:fetch,pull,clone

二. git 的三个分区

首先,在进入 Git 的各种操作之前,一定要明白 git 的三个「分区」是什么,否则的话你一定没办法真正理解 Git 的原理。Git 的三个分区分别是:working directory,stage/index area,commit history。

working dir index(stage) head add commit working dir index(stage) head

working directory 是「工作目录」,也就是我们肉眼能够看到的文件,后文我们称其为 work dir 区。
当我们在 work dir 中执行 git add 相关命令后,就会把 work dir 中的修改添加到「暂存区」stage area(或者叫 index area)中去,后文我们称暂存区为 stage 区。
stage 中存在修改时,我们使用 git commit 相关命令之后,就会把 stage 中的修改保存到「提交历史」 commit history 中,也就是 HEAD 指针指向的位置。后文我们称「提交历史」为 history 区。
关于 commit history 我们多说几句,任何修改只要进入 commit history,基本可以认为永远不会丢失了。每个 commit 都有一个唯一的 Hash 值,我们经常说的 HEAD 或者 master 分支,都可以理解为一个指向某个 commit 的指针。
work dir 和 stage 区域的状态,可以通过命令 git status 来查看,history 区域的提交历史可以通过 git log 命令来查看。
好的,如果上面的内容你都能够理解,那么本文就完全围绕这三个概念展开,下面就是一个关系图:

working dir index(stage) head add commit commit reset checkout checkout working dir index(stage) head

三.本地git简化教程

  • 需求一,如何把 work dir 中的修改加入 stage
    这个是最简单,使用 git add 相关的命令就行了。顺便一提,add 有个别名叫做 stage,也就是说你可能见到 git stage 相关的命令,这个命令和 git add 命令是完全一样的。
    理由:不会改变任或撤销任何已作出的修改,而且还会将 work dir 中未追踪的修改(Untracked file)添加到暂存区 stage 中进行追踪。
  • 需求二,如何把 stage 中的修改还原到 work dir 中。
    这个需求很常见,也很重要,比如我先将当前 work dir 中的修改添加到 stage 中,然后又对 work dir 中的文件进行了修改,但是又后悔了,如何把 work dir 中的全部或部分文件还原成 stage 中的样子呢?
    来个实际场景,我先新建两个文件,然后把他们都加到 stage:
$ touch test1.txt test2.txt
$ git add .
$ git status
On branch master
Changes to be committed:
	new file:   test1.txt
	new file:   test2.txt

然后我又修改了test1.txt文件。

$ echo hello world >> test1.txt
$ git status
On branch master
Changes to be committed:
	new file:   test1.txt
	new file:   test2.txt

Changes not staged for commit:
	modified:   test1.txt

现在,我后悔了,我认为不应该修改 test1.txt,我想把它还原成 stage中的空文件,怎么办?
答案是,使用 checkout 命令:

$ git checkout test1.txt
Updated 1 path from the index

$ git status
On branch master
Changes to be committed:
	new file:   test1.txt
	new file:   test2.txt

输出显示从 index 区(也就是== stage == 区)更新了一个文件,也就是把 work dir 中 test1.txt 文件还原成了 stage 中的状态(一个空文件)。
当然,如果 work dir 中被修改的文件很多,可以使用通配符全部恢复成 stage

git checkout *

有一点需要指出的是,checkout 命令只会把被「修改」的文件恢复成 stage 的状态,如果 work dir 中新增了新文件,你使用 git checkout . 是不会删除新文件的。

  • 需求三,将 stage 区的文件添加到 HEAD(history)区。
    很简单,就是 git commit 相关的命令,一般我们就是这样用的:
$ git commit -m '一些描述'

再简单提一些常见场景, 比如说 commit 完之后,突然发现一些错别字需要修改,又不想为改几个错别字而新开一个 commit 到 history 区,那么就可以使用下面这个命令:

$ git commit --amend

这样就是把错别字的修改和之前的那个 commit 中的修改合并,作为一个 commit 提交到 history 区。

  • 需求四,将 history 区的文件还原到 stage 区。

这个需求很常见,比如说我用了一个 git add . 一股脑把所有修改加入 stage,但是突然想起来文件 test1.txt 中的代码我还没写完,不应该把它 commit 到 history 区,所以我得把它从 stage 中撤销,等后面我写完了再提交。

$ echo aaa >> test1.txt; echo bbb >> test2.txt;
$ git add .
$ git status
On branch master
Changes to be committed:
	modified:   test1.txt
	modified:   test2.txt

如何把 test1.txt 从 stage 区还原出来呢?可以使用 git reset 命令:

$ git reset test1.txt

$ git status
On branch master
Changes to be committed:
	modified:   test2.txt

Changes not staged for commit:
	modified:   test1.txt

你看,这样就可以把== test1.txt == 文件从 stage 区移出,这时候进行 git commit 相关的操作就不会把这个文件一起提交到 history 区了。

上面的这个命令是一个简写,实际上 reset 命令的完整写法如下:

$ git reset --mixed HEAD test1.txt

其中,mixed 是一个模式(mode)参数,如果 reset 省略这个选项的话默认是 mixed 模式;HEAD 指定了一个历史提交的 hash 值;test1.txt 指定了一个或者多个文件。

该命令的自然语言描述是:不改变 work dir 中的任何数据,将 stage 区域中的 a.txt 文件还原成 HEAD 指向的 commit history 中的样子。就相当于把对 a.txt 的修改从 stage 区撤销,但依然保存在 work dir 中,变为 unstage 的状态。

  • 需求五,将 work dir 的修改提交到 history 区。
    这个需求很简单啦,先 git add 然后 git commit 就行了,或者一个快捷方法是使用命令 git commit -a。
  • 需求六,将 history 区的历史提交还原到 work dir 中。
    这个场景,我说一个极端一点的例子:比如我从 GitHub 上 clone 了一个项目,然后乱改了一通代码,结果发现我写的代码根本跑不通,于是后悔了,干脆不改了,我想恢复成最初的模样,怎么办?

依然是使用 checkout 命令,但是和之前的使用方式有一些不同:

$ git checkout HEAD .
Updated 12 paths from d480c4f

这样,work dirstage 中所有的「修改」都会被撤销,恢复成 HEAD 指向的那个 history commit

注意,类似之前通过 stage 恢复 work dircheckout 命令,这里撤销的也只是修改,新增的文件不会被撤销。

当然,只要找到任意一个 commit 的 HASH 值,checkout 命令可就以将文件恢复成任一个 history commit 中的样子。
建议谨慎使用。这个操作会将指定文件在 work dir 的数据恢复成指定 commit 的样子,且会删除该文件在 stage 中的数据,都无法恢复,所以应该慎重使用。

三.远程git简化教程

3.1 创建本地仓库与远程仓库的SSH密匙

ssh-keygen -t ecdsa -b 521 -C "825830916@qq.com"
gedit ~/.ssh/id_ecdsa.pub

复制id_ecdsa.pub的全部内容,这种SSH传输方式非常快速便捷。
在这里插入图片描述
在github setting之中找到SSH and GPG keys 添加。
在这里插入图片描述
在这里插入图片描述
将id_ecdsa.pub中的内容复制到新建的 SSHkey中。

3.2 git fetch 和 git pull

git fetch和git pull都可以将远端仓库更新至本地那么他们之间有何区别?想要弄清楚这个问题有有几个概念不得不提。

FETCH_HEAD: 是一个版本链接,记录在本地的一个文件中,指向着目前已经从远程仓库取下来的分支的末端版本。
commit-id:在每次本地工作完成后,都会做一个git commit 操作来保存当前工作到本地的repo, 此时会产生一个commit-id,这是一个能唯一标识一个版本的序列号。 在使用git push后,这个序列号还会同步到远程仓库。

有了以上的概念再来说说git fetch
git fetch:这将更新git remote 中所有的远程仓库所包含分支的最新commit-id, 将其记录到.git/FETCH_HEAD文件中
git pull : 首先,基于本地的FETCH_HEAD记录,比对本地的FETCH_HEAD记录与远程仓库的版本号,然后git fetch 获得当前指向的远程分支的后续版本的数据,然后再利用git merge将其与本地的当前分支合并。所以可以认为git pull是git fetch和git merge两个步骤的结合。
因此,git fetch是从远程获取最新版本到本地,但不会自动merge。
而git pull则是会获取所有远程索引并合并到本地分支中来。效果相同时git pull将更为快捷。

3.3 项目实例

这里拿我前些天在github仓库新建的项目为例。

  • 需求一 :将本地仓库内容上传到远端
echo "# DIY_CPU" >> README.md
git init
git add README.md
git commit -m "first commit"
git config --global user.email "you@example.com"
git branch -M main
git remote add origin git@github.com:tongjiaxuan666/DIY_CPU.git
git push -u origin main

其中origin 远程在本地的别名。
通过push命令将本地的history HEAD指向的版本提交上去。

  • 需求二:远程仓库有所更改,但是本地没有更改,如何更新的最新版本。
    在做好上述远程和本地链接的步骤后。
git  fetch --all
git  pull

现在本地版本就是远程的最新版本了。

四. git在线练习平台

这是个叫做 Learning Git Branching 的项目,是我一定要推荐的:
在这里插入图片描述
这个网站的教程不是给你举那种修改文件的细节例子,而是将每次 commit 都抽象成树的节点,用动画闯关的形式,让你自由使用 Git 命令完成目标:

在这里插入图片描述
所有 Git 分支都被可视化了,你只要在左侧的命令行输入 Git 命令,分支会进行相应的变化,只要达成任务目标,你就过关啦!网站还会记录你的命令数,试试能不能以最少的命令数过关!
我一开始以为这个教程只包含本地 Git 仓库的版本管理,后来我惊奇地发现它还有远程仓库的操作教程!在这里插入图片描述
网站地址:https://learngitbranching.js.org

对于使用GitHub的技巧,这里有一些建议: 1. 使用分支(Branches):分支是在项目中进行开发、测试和合并更改的好方法。您可以创建新的分支来进行特性开发,确保主分支保持干净和稳定。 2. 编写清晰的提交信息:为每个提交提供有意义的描述,确保其他人能够理解您做了什么更改。这对于回顾历史记录和协作很重要。 3. 使用代码审查(Code Review):通过请求其他人审查您的代码,可以获得有价值的反馈和改进建议。这有助于提高代码质量和团队合作。 4. 使用Issue和Pull Requests:在项目中使用GitHub的Issue和Pull Request功能来讨论问题、提出功能请求和进行代码审查。这有助于组织和追踪项目中的任务和更改。 5. 利用GitHub Actions:GitHub Actions是一个强大的自动化工具,可以帮助您执行各种操作,如测试、构建和部署。您可以根据需要创建自定义的工作流程。 6. 使用项目面板(Project Boards):GitHub的项目面板功能可帮助您组织和跟踪项目任务。您可以创建自定义列来表示各个阶段,并将问题和Pull Request与适当的列关联起来。 7. 学习使用GitHub的高级搜索功能:利用GitHub的高级搜索功能,您可以轻松找到感兴趣的项目、代码片段和问题。这对于学习和发现新东西很有帮助。 希望这些技巧对您有所帮助!如果您有其他问题,请随时提问。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪中奇侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值