/learnGit

Primary LanguagePython

Git is a version control system.
And I think Git is so fucking difficult to learn now :(

安装git
用 sudo apt-get install git 进行安装,用源码包安装的方法我还没成功,原因是没看懂说明中的那三个步骤: ./config ---> make ---> makeall


	git 在使用前要进行一些设置:
sudo git config --global user.name"You Name" #设置你使用git是的“昵称”
sudo git config --global user.email"You E-mail" #设置你的E-mail
这两句必须要有 ,其中--global 参数表示这两个设置应用与git的全局,当需要对某一个“仓库”进行特殊设定时再单独设定。如果没有这两个设定则对git后面的操作将会受限制。

	在安装和设置好git后,就可以使用git了。git形象的说是用于创建一个 个“云仓库”,我们可以在这些仓库中修改,加入或删除文件,然后将这些变化信息上传网络,于是在别处的运仓库就可以通过命令查询到这些变化,如果别的仓库需要这些变化,就可以从改动的仓库中调动文件过来,这样新仓库的文件就得以更新。


	git中的仓库称为 “repository” ,git的所有改动都必须在已有的仓库目录中进行。在PC中没有repository时,可以:
mkdir learngit
cd ./learngit
创建一个文件夹 learngit并切入。随后使用:
git init
这样就将learngit文件夹变成了一个repository。设定这个命令后会发现当前目录下出现一个./.git的文件夹,这事git的内部版本控制记录用的文件(默认是隐藏的,想看可以用 ls -ah),不懂不要改,也不需要改。

	设定完成后就可以在learngit中放入文件或改动文件了。改动后需要提交改动记录给 ”云记事本 “ ,这时候会用两个指令 (例如增加了一个readme.txt 文件):
git add readme.txt
git commit -m "I add a txt file"
	git add命令是用于将 readme.txt放到repository中,因为readme.txt在learngit目录下并不以为着这个文件就 “ 过户 ” 到仓库中,就像仓库是一个快递站点,现在运来了一批快递放在这个站点中,在快递员没有在相应快递上签字签收前,这些快递都不属于这个站点,这样发错的快递和隔壁老奶奶放在这的大葱就都仅仅是暂时放在这里,不会入库存放。
	git commit 命令是将放在repository中的文件提交导git。这是什么意思呢?并且这个和add命令有什么区别? commit命令将文件提交git中并不是真正的提交文件本身或者其副本。git是一个分布式的文件管理系统,与集中式文件管理系统不同,分布式管理系统的没有所谓的**服务器,文件不是由一个总服务器存储,而是由各个小站点存储。而git提交的是文件更改的信息,什么是信息,就是我更改了哪个文件中的那几行(视频,图片或者word这种二进制文件无法详细知道哪些行更改)。git的服务器就不是像集中式管理系统那样存储文件了,而是像一个公告牌,上面列出了文件的变动信息。这时候当别人需要更新文件时,用户通过键入命令,站点的git软件就会查询git公告牌中的更新信息,然后根据信息去请求存放更新文件的那个站点,从那里取回更新的文件。 -m是 commit的一个参数,用于加入更新信息的说明,这里更新的信息说明是"I add a txt file",可以没有说明直接提交更改文件,命令还没查。
	要注意,文件每一次改动后想上传,必须先使用git add命令,就算之前已经add过这个文件也要这样,并且git add可以一次add多个命令。例如 : git add 1.txt hello.c。之后使用的git commit命令是批量性的一次提交所有add的文件,所以可以先分别add 文件,最后一起commit。



	有时候忘记了自己改动了什么文件,过着什么文件没有add,到底有没有commit。这时候可以在命令行键入:
git status
这个命令可以显示当前所在repository的状态。



		当多次更新文件库后,想要查询更新的日志,可以使用:
git log 
这条命令会显示更新的信息,即“云黑板”上的信息。git为每个更新信息明明一个commit ID。这个ID是唯一识别更新信息的编号,为了防止多个用户更新时造成的编号冲突,commit ID设定的位数很长,这个ID为以后的提供了依据。git log指令还可以写成
git log --pretty=oneline
后面的参数会使更新信息显示的很简介,只有commit ID 和每次更新输入的commit。

	版本更换
	当需要退回之前的更新版本时,git是一个十分好用的工具,因为只要你在适当的时间点commit相应的“更新”,那么都可以退回相应的commit版本。例如,输入
git log --pretty=oneline
终端输出:
-----------------------------------------------------------------------------------------------------------------------------------
3a182da1aff2b390701deaccd486f28a422f1973 txt文件加入了一句话
282de35949d72a3156f8459d250ea7c96a43b8bf 加入一个txt文件
4d75f7d4533ad133e1724878f11961dfdde29f66 once again
5288587a8787064e7077599938500ec9a2899a27 add more
760e06670210e688199638549711ea69eecadfb4 add the steps to install and initalise Git
b0b1301485b87f80ef8c6a2c33d1c0c54c81e773 some to add
5ded0241e9869fb7fda2f6c972cbbb9bcaae5534 add a .py file
70f7f762b931728e6dbc690db4a91bb32efcc791 wrote a readme file
-----------------------------------------------------------------------------------------------------------------------------------
这时,文件的最新版本是第一行(commit是“txt文件加入了一句话")。这时候,如果突然发现一个文件提交错误,想要退回上一个文件状态时,只需要输入:
git reset --hard HEAD^
这时候终端将会显示:
HEAD is now at 282de35 加入一个txt文件
然后再使用git log --pretty=onelone时会显示:
-----------------------------------------------------------------------------------------------------------------------------------
282de35949d72a3156f8459d250ea7c96a43b8bf 加入一个txt文件
4d75f7d4533ad133e1724878f11961dfdde29f66 once again
5288587a8787064e7077599938500ec9a2899a27 add more
760e06670210e688199638549711ea69eecadfb4 add the steps to install and initalise Git
b0b1301485b87f80ef8c6a2c33d1c0c54c81e773 some to add
5ded0241e9869fb7fda2f6c972cbbb9bcaae5534 add a .py file
70f7f762b931728e6dbc690db4a91bb32efcc791 wrote a readme file
-----------------------------------------------------------------------------------------------------------------------------------
一切就这么轻松的完成。我们已经回到了”加入一个txt文件“ 这个版本了,这时候repository中的文件就回到了改动之前。对于git reset --hard HEAD^ 这条命令,reset是重新设置的意思;--hard的意思以后再说。 后面的HEAD表示当前所在的版本状态。git内部有一个指向当前版本的指针,名叫HEAD,所以git的版本变换实质是git将HEAD指针指到相应的状态位置,然后顺便把文件更换就完事儿了。git使用 ^ 来表示退回版本的个数,HEAD^的意思就是退回到上个版本。同理,HEAD^^是上上个版本本,那么问题来了,如果想要退回上50个版本呢?连续有50个 ^ 显然十分不方便而且容易出错,这时候就可以使用
git reset --hard HEAD~50
这样就可以快速回到从前美好的时光。
	
	有时候人的脑子会进入牛角尖,当你退回到上一个版本后,从逻辑上来讲就不知道后面的commit,现实也是如此。使用HEAD^后,
3a182da1aff2b390701deaccd486f28a422f1973 txt文件加入了一句话
这一句状态就会无影无踪,那么此时如果突然又想回到 “ 未来 ”该如何是好? 还记得之前说过关于git管理版本的机制吗?git仅仅将HEAD的指向做了改变,所以未来的那个commit并没有消失,只是被隐藏了起来,这时候,commit ID的作用就体现出来了,只要我们知道未来版本的commit ID,就可以使用命令:
git reset --hard 3a182da
如此就可以穿越时空,“ 回 ” 到未来。commmit ID如此之长,我们不需要完全输入,只需要保证commit ID可以被唯一识别即可,例如上面的命令仅仅如数了3a182da。
那么问题又来了,现实就是这么纠结。当我终端没有关闭的时候,我可以通过上拉显示记录找到未来的commit ID,可是如果我关闭了终端或者关机睡觉第二天想要玩穿越怎么办?那个亲人一般的 commit ID已经“ 丢 ” 了。这时候我们并没有穷途末路,我们可以输入:
git reflog
来查询到目前位置所有对于repository的commit操作和reset操作。也会显示每次commit后git赋予的commit ID的前几位。




Git 工作区和暂存区
	这是Git很重要的两个概念,也是很多命令的之所以那么使用的原因。
(等能截图了再继续)






Git撤销操作
	Git可以使用git reset HEAD^ 命令退回上个版本,这是在已经commit后的退回办法。
	Git在一个resposity中有工作区,暂存区和分支这几个地方。在我们修改或添加文件/目录的时候,是在工作区(working directory)中,当我们完成一次作业后,输入git add <file1>...<filen> 命令,将工作区的修改信息提交到Git版本库(resposity)中的暂存区(stage或index)内,此时我们仍然不算将改动并入版本提交分支(分支的概念后面再说)。就像我们在学校当老师,一次考试后我们进入一个改卷小组改卷子。桌子上有一摞要改的卷子,我们正常工作,改那些要改的卷子,这是我们的工作。卷子是按考场装订的,每个考场的卷子钉成一个本子。我们改完了一个本子,就把这一本卷子放在桌旁的一个框子中。当我们一本一本的改卷子并将那个框子装满都时候,我们就拿起这个框子,将它送到另一个老师手里,让老师继续改他负责的题目。我们的桌子就是工作去,框子就是暂存区。我们add交到暂存区的文件修改信息并不是真正的进入了总的修改信息中,而是在我们使用commit命令后才会将这个篮子中的信息提交上去。为什么这样做呢?这个好处就像我们的一个工作进度表,在工程大的时候我们很难记住我们的工作进度或者改动的记录,所以暂存区就起到了一个提醒和检查缓冲的作用,我们可以在commit之前有机会发现并撤销add的改动信息从而增加工作的准确度。
	那么问题来了,我们在没有键入add 或者commit 之前的文件改动都是在工作区中,当我们想要撤销工作区的改动要怎么做?这种场景一般会发生在两种情况下:
一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;	
一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
这两种情况下,我们都可以使用:
git checkout -- readme.txt
让文件回到最近一次 git commit 或者 git add时的状态。
注意: -- 符号的左右都有一个 空格。
-- 这个符号很重要,如果没有这个符号那命令的意思是切换到另一个分支,这个后面再说。

	我们认真工作,将working directory中的文件都改完,然后我们git add <file>... 将他们的改动放入暂存区。我们出去喝了杯大麦茶放松了一下身心,然后回到电脑前,突然发现:刚刚add的信息有错误,例如我们多打了一段不应该说的话。那么这时候改动已经进入了暂存区,git checkout --<file>是不能撤回已经放入暂存区中的信息的。经过一番查阅资料我们发现,Git已经队这种情况提供了撤销操作。Git告诉我们,用命令
git reset HEAD file 
可以把暂存区的修改撤销(unstage)掉,重新放回到工作区中。注意,这时候我们是把暂存区的改动信息撤销回工作区中,并没有紧接着将工作区的内容撤销,所以如果是想把暂存区的更改完全撤销,要继续输入 git checkout --file 撤销工作区改动。

	注意:撤销不会“退回”,用git reset HEAD file 将更改信息从暂存区撤销掉并不是将更改的内容“打回”工作区,使用git reset HEAD file并不影响当前工作区中文件的内容。例如当我们在
git add readme.txt
后,又对readme.txt的内容进行了修改,例如删除了一行文字,这时候我们使用
git reset HEAD readme.txt
仅仅是将送到暂存区的更改信息删掉了,而工作区中当前的readme.txt里面那条我们删除的一行(在add 时是存在的)也不会再次出现。