Git自学记录
记录下git及github的自学使用过程,做项目和整理代码总要用到这些的。
非科班,纯小白。最近学到的道理是,先做,再做好。
(不是教程,只是学习记录,所以学了新的东西可能也会更新)
部分内容的学习参考视频
是什么
万一面试问到了呢~
Git是一种VCS (Version Control System) ,即版本控制系统。
初始配置
Git的官网下载地址:官网下载地址
以windows为例。
Portable是便携版,查询了一下,标准版Git需要双击安装,而便携版是压缩包,解压后不需要安装等等。
我们这里还是选择下载标准版吧。
下载速度感人的话,自己用魔法,我就不教了。
另:这里测试了一下uu加速器的学术模块,好像没法加速下载。
点击安装,除了安装路径可以改改,其他的无脑点next即可。
初始设置
安装完成后,会发现右键菜单多了两个选项。
我们选择第二个。(因为第一个我没有学)
打开之后就是这个熟悉的命令窗口(梦回cmd、Anaconda Prompt)
ok!来写第一条指令,配置一下用户和邮箱吧。
config:configuration,配置
git config --global user.name 随便取一个
git config --global user.email 邮箱@也能随便取
补充:如果你想起个带空格的用户名:
git config --global user.name "有空格 也行" # 需要加双引号
用户和邮箱的作用在于:在提交(commit) 时标识是谁提交的。
设置完成后,我们可以用命令检查一下:
git config --global user.name
git config --global user.email
代码管理
写代码是反复修改的过程,如果不小心改崩了,那我们希望至少回退到某个代码尚且正常的时间点。
但是这种方法不适用于多人合作项目的情形。
而且,时不时存储一个版本也太麻烦了, (至少我肯定想不起来存)
所以我们才使用Git来帮助管理代码。
学会白嫖
众所周知,github是白嫖圣地x 你可以通过点击code直接下载压缩包来白嫖代码。
也可以用Git来白嫖:
在你想要存储代码的文件夹中Git Bash Here
,并在命令窗口输入:
git clone 你刚刚复制的那行链接
clone成功后:
打开文件夹,发现已经成功白嫖。
.git
里的是版本管理相关的文件,大部分时间和你无关,别去动它就行。
和直接从Github下载的区别是,多了一个.git
,也就是说,不只是白嫖了代码,而是白嫖了一整个仓库。可以看到修改/提交记录等。
一些乱七八糟的功能测试。Github为什么不能创建空文件夹……!
管理和提交
我们使用Git,更多地还是希望管理自己写的代码。
在你选定的文件夹中,右键Git Bash Here
,打开命令窗口。
git init
出现了.git
。即,Git已经知道需要在此帮你管理代码了。
ok,随便整点东西进来。
除了.git
之外的其他文件,都在工作区。(你在本地电脑看到的目录。)
进行一次提交测试。先选中当前项目的所有文件(除了.git
和空文件)
git add .
然后提交
git commit -m "这里写点注释" # windows平台使用双引号,linux单引号
-m
的意思是message,不写注释的话,回头版本回退你都不知道退到哪。
(写注释是好习惯!对我这种学得快忘得快的尤其重要)
16 files changed
:16个文件被改动(新增)
10590 insertions(+)
:插入了10590行内容(有这么多行内容,是因为我传入了多个数据集,所以数字比较大)
看下提交记录
git log
再试一次!修改一下main.py
,进行提交。
写注释然后commit
……诶?不得不尝的报错
解读一下:
modified
:已更改。但还没有被暂存到Git的索引中,这意味着这些更改不会被包含在下一次的提交中。
staged
:已暂存。这些更改会被包含在下一次的提交中。
所以每次都得先“上膛”add
再“发射”commit
。
话说回来,我只修改了这一个文件。那么也只提交这一个文件吧,节省时间。
检查一下log
:
一切正常~
版本回退
假设代码丢失,或者改出问题了:
至少README.md
文件还在。将其回退至最新一次提交的版本。
git checkout --你要恢复的文件名
再打开README文件看看。
好好好,至少恢复一个。
(注意:checkout
命令会覆盖掉本地的修改。一定要注意操作对象,以及做好保存和备份。)
删除的文件也可以这样恢复。但是万一文件数量很多,或者我 忘记文件名字了怎么办?
尝试彻底恢复到某一版本:
git reset --hard 目标版本的哈希值
都恢复啦。
Git常用操作
commit
提交,记得先add
哦。
git commit -m "注释"
分支
创建分支
git branch 分支名
不过,如果这时你直接commit
提交改动,提交的记录仍会更新在master
分支上。
这是因为你当前仍“在”master
分支上。所以,需要先转到该分支
git checkout 分支名
之后再提交,记录就会更新到分支上了。
HEAD
通常是HEAD->分支名->节点
,但如果你直接checkout
某一结点/版本,则变成HEAD->节点
。
总而言之就是指向当前节点。
合并
初始分支情况,一个简单的分叉。
① merge
将要提交的分支b 合并到目标位置 *分支a(当前在 *分支a,也就是下图里的main)
git merge 分支b
merge
一下bugFix
分支给自己。
相当于分支a(main
)前进了一步,分支a包含了所有修改。
同样的,如果你想更新分支b(bugFix
),使其推进一步,也包含所有修改,那就先git checkout 分支b
,再进行merge
操作。
这样分支b也能享受所有修改了。
总结:拿来吧你。
② rebase
git rebase 目标位置 要提交的记录
# 先切换到要提交的记录
git rebase 目标位置
rebase
到main
,爱来自bugFix
。
可以看到rebase
的合并方式更线性。当前所在分支(bugFix
)copy一个副本过来,接到被rebase
的分支(main
)下。
而merge
方法则是在当前所在分支(bugFix
)后更新。不一样耶。
总结:我过去。
另:git rebase -i 目标位置 (当前所选节点)
可开启交互式窗口,调换(从HEAD到目标位置之间的所有)记录的位置。
相对引用
回溯时也可以不使用哈希值,使用相对引用。
① ^
如分支名^
,HEAD^
等,
② ~数字
一般还是建议使用哈希值,因为实际应用中Git并不是非常直观。
补充:那么^
后加数字代表什么呢?
前面我们学习了merge
,合并后的节点可能有不止一个父节点(parent
),通常默认第一个parent
,但当我们想要指向/查询其他父节点时,就可以使用^数字
啦。
^
和~
都支持链式操作。
修改分支位置
git branch -f 要移动的分支名 目标位置
你可以使用哈希值,或者相对引用,来表示目标位置。
复制你的提交
cherry-pick
将记录复制到当前所在位置HEAD
下,可以选择多个记录。
git cherry-pick 记录1 记录2 ...
修改你的提交
如图,更新一下c2'
,变成c2''
。
git commit --amend
打标签
git tag 标签名 所选节点
若没写所选节点,则默认为HEAD
所在的节点。
通常用于记录大版本更新,类似里程碑、锚点(标签是不会变的)
查询标签
git describe <指定的节点>
未指定,则默认为HEAD
。
其会输出:
<tag>_<numCommits>_g<hash>
翻译成人话:
<距离最近的标签>_<距离多少个提交记录>_g<你指定的节点的哈希值前几位>(如果你指定的节点本身就有标签,则输出标签名)
和Github的联动(远程仓库)
远程分支的命名规范:<远程仓库名称>/<分支名>
,例如origin/main
。(虽然叫origin,但只是远程仓库的默认初始名,是远程)
在本地尝试操作远程分支时会怎么样?例如,先checkout
远程分支,再直接commit
答案:会导致HEAD
分离,分支指针动都不会动的。
我们看一下本地和远程的两种commit
情况:
①本地
指针正常移动。
②远程
*警告!现在是分离HEAD状态。
指针不动。
获取数据
git fetch
从远程仓库获取数据,并更新远程分支。
即,与远程仓库进行通信的方式。
git fetch
通常通过互联网(使用 http://
或 git://
协议) 与远程仓库通信。
注意:
git fetch
并不会改变你本地仓库的状态,只是一个下载操作。
它不会更新你的main
分支,也不会修改你磁盘上的文件。
只会更新origin/分支
。
git pull
你可以先fetch
拉取更新,再使用cherry-pick
、rebase
、merge
等来合并远程分支。
也可以直接二合一,使用git pull
操作。
git pull = git fetch + git merge
git pull --rebase = git fetch + git rebase
关于合并远程分支,下面会解释。
git push
和pull
相反,push
用于上传和分享。
远程仓库中的指针(例如,远程仓库的main
),以及我们本地的远程分支指针(例如,origin/main
),都会更新。
在实际工作中,由于 历史偏移 的存在,你可能无法正常git push
。你需要保证你的工作基于最新的远程分支。
①rebase
左边是本地,右边是远程。
本地你写了c3
,但同事们在远程更新了c2
。
处理方法:
git fetch
git rebase o/main
#也可以直接git pull --rebase
从远程仓库fetch
来c2
,再把自己的c3
给rebase
到c2
上。
告诉git,自己的工作是基于最新的远程分支做的。
git push
如此,再进行push
就可以了。
②merge
merge
是不会移动你的工作的,它会创建一个新的提交。
git fetch
git merge o/main
#也可以直接git pull
git push
push的情况和rebase
不太一样。rebase
依旧是更加线性。
不得不尝的报错和bug
1. git clone时报错
可参照这篇博客的内容进行解决。
2. LF will be replaced by CRLF the next time Git touches it
这个bug我只有第一次触发了,后面想截图结果没再出现过了。
但以防万一还是贴一下解决方法
总之:
false:忽略不管。不建议设置成这个。
true:提交(commit)
时CRLF(Windows)->LF(Linux),checkout
时LF(Linux)->CRLF(Windows)。
本地是CRLF,适合windows
input:提交(commit)
时CRLF(Windows)->LF(Linux),checkout
时不转换。
本地是LF,适合linux
更深一些的:core.autocrlf=true 是有争议的配置
总而言之就是多人协作情况下,自己改了配置可能导致别人出错。因此建议使用.gitattributes
规范配置,更适合多人协作情况。有空再细化。
非常推荐
Git教程游戏 建议多玩几遍,形象生动。要是所有自学课程都能这样白痴向就好了,我喜欢。