首页 > 代码库 > 廖雪峰Git教程学习笔记

廖雪峰Git教程学习笔记

廖雪峰git简单教程学习笔记

教程地址:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000
1、可以这样设计目录,在d:\reposisoty\ 在这个目录下面有很多的仓库。
mkdir learngit
cd learngit
>>git init          #这样就把learngit 初始化成了一个仓库
>>git status        #说明当前仓库的状态并且会提醒你可能可以做的操作
在learngit目录下面新建一个文件readme.txt,并添加到git仓库中,一次如下的操作
>>git add readme.txt
>>git commit -m "wrote a readme file"   #-m后面是说明性的文字,方面查看修改的内容
把一个文件提交到git仓库中分为上面两部,add命令可以一次添加很多文件,依次用空格分开,比如向下面这样:
>>git add file1.txt file2.txt
>>git commit -m "add 2 files"

2 版本、撤销……相关
2.1 修改上面创建的 reame.txt文件的内容,然后
>>git status    #这个命令可以让我们时刻掌握仓库当前的状态。
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   readme.txt

no changes added to commit
上面的信息告诉我们readme.txt被修改了,但是还有装备调教的修改,这是我们可以使用git diff来查看做出了怎样的修改。
>>git diff readme
diff --git a/readme.txt b/readme.txt
index 629f6b7..be836b4 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system
+Git is a distributed version control system
 Git is free software
\ No newline at end of file
-表示这一行消失了,+表示这一行是后来出现的
知道文件做了什么修改,这时我们可以放心的提交文件了。
>>git add readme.txt
>>git status 会提醒当前的工作目录的状态
>>git commit -m "add word distributed"
commit 就是一个快照功能,当你玩DevilCry的时候没过一关,游戏都会有一个存档,当你下次登录游戏的时候可以接着之前的关卡打怪。在git中每次我们git commit -m 时就是我们手动存档。

2.2 版本回退
就是会到对应的commit快照点。可以使用git log 来查看所有的commit点
>>git log       #列出对应的commit点
如果嫌输出的内容较多可以加上参数 --pretty=oneline
git log --pretty=oneline    如下:
8debcc13d05bd5627a01c875e20780523f572ba7 append gpl
dc79b71e4175992e89c3539c10710ad87a2fd54e add a word [distributed]
e0e4517d9b45969ba73b111bc59a42f7a97fe71a wrote a readme file

在git中,当前版本用HEAD表示,上一个版本用HEAD^,上上一个版本用HEAD^^,一次类推,当然太多的时候,^数不清,这个时候我们用HEAD~100表示之前的第100个版本。
>>git reset --hard HEAD^    就会回退到前一个版本
这是在查看git log --pretty=oneline会发现只剩下两个commit了。
dc79b71e4175992e89c3539c10710ad87a2fd54e add a word [distributed]
e0e4517d9b45969ba73b111bc59a42f7a97fe71a wrote a readme file
如果再想回退到最新的版本。这是可以使用git reflog 来查看命令历史:
$ git reflog --pretty=oneline
dc79b71 HEAD@{0}: reset: moving to HEAD^    #注意 使用commitid时,只需要7位就够了
8debcc1 HEAD@{1}: commit: append gpl
dc79b71 HEAD@{2}: commit: add a word [distributed]
e0e4517 HEAD@{3}: commit (initial): wrote a readme file
使用下面的命令:
git reset --hard 8debcc1

2.3工作区和暂存区
工作区(working directory)就是你在电脑中能看到的一个目录,比如之前创建的learngit
版本库(Repository)就是工作区中的一个隐藏的目录.git,这个不算是工作区,而是git的local版本库..git中存放了很多的东西,其中最重要的就是stage(或者称之为index)的暂存区,还有一个git为我们自动创建的master分值,以及一个纸箱master的指针叫做HEAD.HEAD和branch的概念后面介绍。
在来 回头看前面网Git版本库中添加文件的操作,是分两步执行的:
1)git add filename :实际上是把文件修改添加到暂存区;
2)git commit提交更改,实际上是把暂存区的所有内容提交到当前的分支branch
因为我们创建Git版本库的时候,Git自动为我们创建了一个分支branch master,所以现在git commit就是网master上面提交东西(因为当前只有一个分支)。一旦使用commit之后,就会吧stage(暂存区)中的内容提交到版本库中的某一个branch,清空stage。

2.4 管理修改。
为什么Git比其他的版本控制系统设计的优秀,因为Git跟踪管理的是修改,而不是文件。Git中修改(changge)是一个广义词,新增一个文件也是一种修改,说这句话的对象是相对于整个Git仓库而言的。
每当我们对某个文件修改之后,如果不add到暂存区,那就不会加入到commit中。

2.5 撤销修改
1)场景:你修改了working flow中的文件,然后别的什么都没做,比如你在readme.txt中加了一行,my stupid boss...。你如果想撤销这个修改。因为这个修改只是在工作区,可以有下面两个选择:
    i)手动删除掉readme.txt的内容
    ii)>>git checkout -- readme.txt.这条语句可以把readme.txt在工作区的修改全部撤销。这条命令执行以后会让文件回到最近一次git commit或者git add时的状态。
2)场景:在工作区修改完以后,执行了
git add readme.txt
操作,这时修改已经到了stage暂存区了,也就是说在commit的话,就要进入本地版本库的某一个branch了。这时stage中的内容是我们不想要的,如果此时commit的话,版本就要被刷新了,因为已经执行过了add操作,所以working flow和stage中的readme.txt是一样的,这时要想撤销修稿,我们可以使用如下步骤:
    i)git reset HEAD readme.txt然后在丢弃工作区的修改,使用场景1)中指令:
    ii)git checkout -- readme.txt
3)场景:已经完成了git commit -m "message"也就是说,影提交到本地的master分支了,这个时候使用前面提到的,版本回退指令:
get reset --hard HEAD^.
如果已经把修改提交到了远程的代码仓库,那么久无力回天了。

说明:要经常用git status指令,并且要回看懂其返回的状态信息:当前branch,接下来怎么做,具体的修改内容是什么。
1)修改working flow中的readme.txt文件之后
$ git status
On branch master                #当前在master branch
Changes not staged for commit:  #还没有add到stage,你可以选择下面的两个操作
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   readme.txt  #具体“什么操作”修改了“那个文件”

no changes added to commit (use "git add" and/or "git commit -a")
                                # 还没有提交commit
                                
如果git add readme.txt之后:
$ git status
On branch master                #当前所在的branch
Changes to be committed:        #说明当前git已经吧修改提交到了stage等待下一步commit
  (use "git reset HEAD <file>..." to unstage)

        modified:   readme.txt  

2.6文件的删除与恢复
比如在learngit中新建了一个文件 tet.txt
git add test.txt
然后 吧文件添加到stage中,git add test.txt
rm test.txt 删除文件
这种情况下可以使用git checkout -- test.txt从 stage中吧文件回复出来
另一种情况,是add test.txt之后然后commit,这个时候rm test.txt可以使用 git reset --hard test.txt回复

3 添加远程仓库
3.1 公共的代码托管仓库是GitHub,当然你也可以搭建自己的Git服务器。这里介绍的是GitHub。当然首先你应当注册一个Github的账户。Git和支持SSH加密通信协议。
1)创建SSH KEy。当然创建之前可以先查看一下主目录下面有没有.ssh目录,这个目录里面(win7.ssh目录在C:\users\administrator下面)有两个文件:id_rsa和id_rsa.pub,这两个是SSH Key的密钥对,前者是私有的,不能泄露,后者是公开的用来告诉别人的。如果没有的话,使用下面的指令创建:
ssh-keygen -t rsa -C "1373779753@qq.com"    #生成 SSH Key,找到上面的文件,把id_rsa.pub中
    的内容拷出来。或者使用下面的指令:
clip < ~/.ssh/id_rsa.pub    #把公共密钥拷贝到剪贴板。
2)登录github账号,然后在setting中add ssh key出,new ssh key,标题任意,粘贴内容。
为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。
当然,GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。

3.2本地有了一个Git仓库,可以在远程的GitHub上面创建一个仓库,远程的仓库既可以作为备份也可以开源给别人。
1)先登录GitHub默认条件创建一个repository,learnit。
2)在本地仓库的Git bash中执行下面的指令,就可以吧本地的Git和远程的Git关联
    git remote add origin git@github.com:yingquliang/learngit.git
添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。
3)git push -u origin master
把本地库的所有内容推送到远程库上。远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支。以后就可以不加 -u参数直接使用:
git push origin master

3.3从远程克隆。
更多的我们都是先在Github远程端上创建一个仓库,然后每个人克隆到本地开始工作。
在github上创建一个远程仓库 gitskills并勾选使用 README.md初始化。还是记住ssh的传输地址,在本地git bash中克隆:
 git clone git@github.com:yingquliang/gitskills.git
 要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。
 
 4.分支管理
分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。
4.1创建与合并分支
分支到底是个啥,Git把每次提交的commit穿成一条时间线,这条时间线就是一个分支。
Git本身就是linux之父用C语言写的,所以呀git里面其实是有很多指针的,这一章节关于分针的原理讲解就是指针的指向变化。
当只有一个主分支master时,master指向的是当前的提交commit,而HEAD指向的是master,所以HEAD就指向了当前的分支。伪码描述:
    master  = current_commit;
    HEAD    = master
当然上面的操作都是git完成的,上面只是为了更好的说明原理。
创建一个新的分支,那么新分支就会指向master,然后head就只想当前的新分支,后续的操作都在新分支上,创建分支的原理如下:
    dev     = master
    head    = dev   之后的commit就在dev分支上
合并分支:master = dev
合并之后,就可以删除 dev = null
当然上面的伪码描述的知识原理。具体的生动详细的讲解,见廖雪峰的页面:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/001375840038939c291467cc7c747b1810aab2fb8863508000

在当前的分支创建一个新的分支的方法:
git checkout -b dev     #创建新的分支dev,并切换到这个新的分支,这条指令是下面两条的缩写:
    git branch cev
    git checkout dev

之后再做的commit都是提交到当前的分支dev的,把设置branch这个事情给记下来:
    git add readme.txt
    git commit -m "branch test"
    # 这些修改都是在新的分支dev上完成的
dev分支的工作完成后,就可以换回到master分支
    git checkout master
然后再问把dev分支上的共偶作成果合并到master分支上:
    git merge dev   # 默认情况吧dev分支合并到当前分支上面
    合并之后甚至都可以直接删除dev分支了:
    git branch -d dev 将会以fast-forward的快速删除方式删除dev扥之
4.2 解决冲突
创建一个新的分支feature1 进行后面的开发:
git checkout -b feature1    #创建 + 切换到feature1分支\        
    然后在这个分支上面修改readme.txt文件,修改最后一行.并把修改提交到当前的feature分支
    git add readme.txt
    git commit -m "AND simple"
做完feature1上面的工作之后,切换回master目录,
    git checkout master #切换到master分支
    接着在master目录下面修改readme.txt文件修改之后,提交到mster。add  /   commit
现在吧feature1 合并到 master上面将会报错,发生冲突,这种充足git会先尝试解决,解决不了的时候,才回跑出来,这个时候你只能手动解决冲突。
    git merge feature1
    Auto-merging readme.txt
    CONFLICT (content): Merge conflict in readme.txt
    Automatic merge failed; fix conflicts and then commit the result.
    这个时候可以打开查看readme.txt文件,发现下面会列出的不同分支发生冲突出逇内容。
手动修改readme中对应错误提示下面的内容,然后 **再 add  commit即可
然后可以使用下面的指令查看,用commit表示的 分支合并路径
$ git log --graph --pretty=oneline --abbrev-commit
*   5d0e866 conflicts fixed
|\
| * 49e5cc0 AND simple
* | 51c63ca & simple
|/
* 47fdfc1 branch test
* a022dcf tack changes of files
* c556222 git tacks changes
* 898a3ab understand how stage work
* 8debcc1 append gpl
* dc79b71 add a word [distributed]
* e0e4517 wrote a readme file
最后再删除分支
git branch -d feature1

4.3分支管理策略
直接使用 git merge dev命令合并dev分支时,将会使用fast-forward策略合并,fast-forward合并分支后,使用git log --graph是查看不到合并图的。为了避免这种情况的发生,可以在merge指令后面加上 --no-ff参数:
    git merge --no-ff -m "merge with no-ff" dev
        注意,这个指令会自动产生一个commit所以最好加上一条commitmessage
然后再用 git log --graph --pretty=oneline --abbrev-commit查看
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
技术分享

4.4bug分支
了bug就需要修复,在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101来修复它,但是,等等,当前正在dev上进行的工作还没有提交。
并不是你不想提交,而是工作只进行到一半,还没法提交,预计完成还需1天时间。但是,必须在两个小时内修复该bug,怎么办?
幸好,Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
    $ git stash
现在,用git status查看工作区,就是干净的(除非有没有被Git管理的文件),因此可以放心地创建分支来修复bug。首先确定要在哪个分支上修复bug,假定需要在master分支上修复,就从master创建临时分支
    $ git checkout master           #切换到主分支
    $ git checkout -b issue-101     #在主分支上创建bug修复的分支
现在修复bug,需要把“Git is free software ...”改为“Git is a free software ...”,然后提交:
    git add readme.txt
    $ git commit -m "fix bug 101"
修复完成后,切换到master分支,并完成合并,最后删除issue-101分支
    $ git checkout master
    $ git merge --no-ff -m "merged bug fix 101" issue-101
    $ git branch -d issue-101
接着回到dev分支干活
    git checkout dev
    $ git status
    # On branch dev
    nothing to commit (working directory clean)
工作区是干净的,刚才的工作现场存到哪去了?用git stash list命令看看
    git stash list
    stash@{0}: WIP on dev: 6224937 add merge
工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:
    一是用git stash apply stash@{0}恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;
    另一种方式是用git stash pop,恢复的同时把stash内容也删了
再用git stash list查看,就看不到任何stash内容了.
回复stash保存的工作现场的方法:
    git stash apply stash@{0}  #恢复到stash@(0) 工作现场
    git stash drop stash@{0}    #删除{0}工作现场
    或者下一条指令,直接完成上面两部的工作:
    git stash pop

4.5Feature分支
软件开发中,总有无穷无尽的新的功能要不断添加进来。
添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。
你终于接到了一个新任务:开发代号为Vulcan的新功能,该功能计划用于下一代星际飞船。
于是准备开发:
$ git checkout -b feature-vulcan
5分钟后,开发完毕:
    $ git add vulcan.py
    $ git status
    $ git commit -m "add feature vulcan"
切回dev,准备合并.
就在此时,接到上级命令,因经费不足,新功能必须取消!
虽然白干了,但是这个分支还是必须就地销毁:
$ git branch -d feature-vulcan
销毁失败。Git友情提醒,feature-vulcan分支还没有被合并,如果删除,将丢失掉修改,如果要强行删除,需要使用命令
    git branch -D feature-vulcan。
    
4.6多人协作
$ git remote    #查看远程库信息
origin
或者,用git remote -v显示更详细的信息:
$ git remote -v
origin  git@github.com:michaelliao/learngit.git (fetch)
origin  git@github.com:michaelliao/learngit.git (push)
上面显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。
推送分支:就是把该分支上的所有本地提交推送到远程库----
    $ git push origin master    #把本地master上面的commit都推送到远程的master上
    $ git push origin dev       #把本地dev上面的commit都推送到远程的master上
    但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?
    master分支是主分支,因此要时刻与远程同步; dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
    feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
抓取分支
多人协作时,大家都会往master和dev分支上推送各自的修改。
模拟一个你的小伙伴,可以在另一台电脑(注意要把SSHKey添加到GitHub)或者同一台电脑的另一个目录下克隆 :
    $ git clone git@github.com:yingquliang/learngit.git
当你的小伙伴从远程库clone时,默认情况下,你的小伙伴只能看到本地的master分支
    $ git branch
    * master
现在,你的小伙伴要在dev分支上开发,就必须创建远程origin的dev分支到本地,于是他用这个命令创建本地dev分支:
    $ git checkout -b dev origin/dev
现在,他就可以在dev上继续修改,然后,时不时地把dev分支push到远程:
    $ git commit -m "add /usr/bin/env"
    [dev 291bea8] add /usr/bin/env
    1 file changed, 1 insertion(+)
    $ git push origin dev
    Counting objects: 5, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (2/2), done.
    Writing objects: 100% (3/3), 349 bytes, done.
    Total 3 (delta 0), reused 0 (delta 0)
    To git@github.com:michaelliao/learngit.git
    fc38031..291bea8  dev -> dev
你的小伙伴已经向origin/dev分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:
    $ git add hello.py
    $ git commit -m "add coding: utf-8"
    [dev bd6ae48] add coding: utf-8
    1 file changed, 1 insertion(+)
    $ git push origin dev
    To git@github.com:michaelliao/learngit.git
       ! [rejected]        dev -> dev (non-fast-forward)
    error: failed to push some refs to ‘git@github.com:michaelliao/learngit.git‘
    hint: Updates were rejected because the tip of your current branch is behind
    hint: its remote counterpart. Merge the remote changes (e.g. ‘git pull‘)
    hint: before pushing again.
    hint: See the ‘Note about fast-forwards‘ in ‘git push --help‘ for details.
推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送:
git pull也失败了,原因是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接:
    $ git branch --set-upstream dev origin/dev
    Branch dev set up to track remote branch dev from origin.
再pull:
    $ git pull
这回git pull成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,提交,再push
    $ git commit -m "merge & fix hello.py"
    [dev adca45d] merge & fix hello.py
    $ git push origin dev
因此,多人协作的工作模式通常是这样:
    首先,可以试图用git push origin branch-name推送自己的修改;
    如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
    如果合并有冲突,则解决冲突,并在本地提交;
    没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!
如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream branch-name origin/branch-name。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。

5 标签管理
发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照。
Git的标签虽然是版本库的快照,但其实它就是指向某个commit的指针(跟分支很像对不对?但是分支可以移动,标签不能移动),所以,创建和删除标签都是瞬间完成的。
5.1创建标签
在Git中打标签非常简单,首先,切换到需要打标签的分支上:
    $ git branch
    * dev
    master
    $ git checkout master
    Switched to branch ‘master‘
然后,敲命令git tag <name>就可以打一个新标签:
    $ git tag v1.0
可以用命令git tag查看所有标签:
    $ git tag
    v1.0
默认标签是打在最新提交的commit上的。
有时候,如果忘了打标签,比如,现在已经是周五了,但应该在周一打的标签没有打,怎么办?
方法是找到历史提交的commit id,然后打上就可以了:
    $ git log --pretty=oneline --abbrev-commit】
    6a5819e merged bug fix 101
    cc17032 fix bug 101
    7825a50 merge with no-ff
    6224937 add merge
    59bc1cb conflict fixed
比方说要对add merge这次提交打标签,它对应的commit id是6224937,敲入命令:
    $ git tag v0.9 6224937
再用命令git tag查看标签:
    $ git tag
    v0.9
    v1.0
注意,标签不是按时间顺序列出,而是按字母排序的。
查看 某个具体标签的信息:
    $ git show v0.9
    commit 622493706ab447b6bb37e4e2a2f276a20fed2ab4
    Author: Michael Liao <askxuefeng@gmail.com>
    Date:   Thu Aug 22 11:22:08 2013 +0800

        add merge……
可以看到,v0.9确实打在add merge这次提交上。
还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:
$ git tag -a v0.1 -m "version 0.1 released" 3628164
用命令git show <tagname>可以看到说明文字:
    $ git show v0.1
    tag v0.1
    Tagger: Michael Liao <askxuefeng@gmail.com>
    Date:   Mon Aug 26 07:28:11 2013 +0800
    version 0.1 released
    commit 3628164fb26d48395383f8f31179f24e0882e1e0
    Author: Michael Liao <askxuefeng@gmail.com>
    Date:   Tue Aug 20 15:11:49 2013 +0800
    append GPL
还可以通过-s用私钥签名一个标签:
    $ git tag -s v0.2 -m "signed version 0.2 released" fec145a 签名采用PGP签名,因此,必须首先安装gpg(GnuPG),如果没有找到gpg,或者没有gpg密钥对,就会报错:
    gpg: signing failed: secret key not available
    error: gpg failed to sign the data
    error: unable to sign the tag
    如果报错,请参考GnuPG帮助文档配置Key。

5.2 操作标签
如果标签打错了,也可以删除:
    $ git tag -d v0.1
    Deleted tag ‘v0.1‘ (was e078af9)
因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除。
如果要推送某个标签到远程,使用命令git push origin <tagname>
    $ git push origin v1.0
    Total 0 (delta 0), reused 0 (delta 0)
    To git@github.com:michaelliao/learngit.git
    * [new tag]         v1.0 -> v1.0
或者,一次性推送全部尚未推送到远程的本地标签:
    $ git push origin --tags
如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:
    $ git tag -d v0.9
如果标签打错了,也可以删除:
    $ git tag -d v0.1
    Deleted tag ‘v0.1‘ (was e078af9)
因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除。

如果要推送某个标签到远程,使用命令git push origin <tagname>:
    $ git push origin v1.0
    Total 0 (delta 0), reused 0 (delta 0)
    To git@github.com:michaelliao/learngit.git
    * [new tag]         v1.0 -> v1.0

或者,一次性推送全部尚未推送到远程的本地标签:
    $ git push origin --tags
    Counting objects: 1, done.
    Writing objects: 100% (1/1), 554 bytes, done.
    Total 1 (delta 0), reused 0 (delta 0)
    To git@github.com:michaelliao/learngit.git
    * [new tag]         v0.2 -> v0.2
    * [new tag]         v0.9 -> v0.9

如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:
    $ git tag -d v0.9
    Deleted tag ‘v0.9‘ (was 6224937)
    然后,从远程删除。删除命令也是push,但是格式如下:
    $ git push origin :refs/tags/v0.9
    
6.使用GitHub 可以在github上把别人的开源项目fork到自己的github仓库中,然后再从自己的仓库中吧这个项目克隆到本地,在本地自己可以接着开发这个项目。然后可以把本地的修改push到自己的github上。可以在github上,把自己修改的项目向原作者pull request。

7 自定义git
7.1git有很多的配置,最开始使用
    git config --global user.name "yourname"
    git config --global user.email "youremaliaddress"
git config --global color.ui true   配置颜色的
还有很多 具体 可以 git config  --help 将会打开帮助文档
7.2忽略特殊文件:
有些时候,你必须把某些文件放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件啦,等等,每次git status都会显示Untracked files ...,有强迫症的童鞋心里肯定不爽。
好在Git考虑到了大家的感受,这个问题解决起来也很简单,在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
不需要从头写.gitignore文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore
忽略文件的原则是:
    忽略操作系统自动生成的文件,比如缩略图等; 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
    忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

举个例子:
假设你在Windows下进行Python开发,Windows会自动在有图片的目录下生成隐藏的缩略图文件,如果有自定义目录,目录下就会有Desktop.ini文件,因此你需要忽略Windows自动生成的垃圾文件:
    # Windows:
    Thumbs.db
    ehthumbs.db
    Desktop.ini

然后,继续忽略Python编译产生的.pyc、.pyo、dist等文件或目录:
    # Python:
    *.py[cod]
    *.so
    *.egg
    *.egg-info
    dist
    build

加上你自己定义的文件,最终得到一个完整的.gitignore文件,内容如下:
    # Windows:
    Thumbs.db
    ehthumbs.db
    Desktop.ini

    # Python:
    *.py[cod]
    *.so
    *.egg
    *.egg-info
    dist
    build
    # My configurations:
    db.ini
    deploy_key_rsa
最后一步就是把.gitignore也提交到Git,就完成了!当然检验.gitignore的标准是git status命令是不是说working directory clean。
使用Windows的童鞋注意了,如果你在资源管理器里新建一个.gitignore文件,它会非常弱智地提示你必须输入文件名,但是在文本编辑器里“保存”或者“另存为”就可以把文件保存为.gitignore了。
有些时候,你想添加一个文件到Git,但发现添加不了,原因是这个文件被.gitignore忽略了:
    $ git add App.class
    The following paths are ignored by one of your .gitignore files:
    App.class
    Use -f if you really want to add them.
如果你确实想添加该文件,可以用-f强制添加到Git:
    $ git add -f App.class
或者你发现,可能是.gitignore写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore命令检查:
    $ git check-ignore -v App.class
    .gitignore:3:*.class    App.class
    Git会告诉我们,.gitignore的第3行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。

7.3配置别名:
有没有经常敲错命令?比如git status?status这个单词真心不好记。
如果敲git st就表示git status那就简单多了,当然这种偷懒的办法我们是极力赞成的。
我们只需要敲一行命令,告诉Git,以后st就表示status:
    $ git config --global alias.st status
好了,现在敲git st看看效果。
当然还有别的命令可以简写,很多人都用co表示checkout,ci表示commit,br表示branch:
    $ git config --global alias.co checkout
    $ git config --global alias.ci commit
    $ git config --global alias.br branch
以后提交就可以简写成:
    $ git ci -m "bala bala bala..."
    --global参数是全局参数,也就是这些命令在这台电脑的所有Git仓库下都有用。

在撤销修改一节中,我们知道,命令git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回工作区。既然是一个unstage操作,就可以配置一个unstage别名:
    $ git config --global alias.unstage ‘reset HEAD‘
当你敲入命令:
    $ git unstage test.py
实际上Git执行的是:
    $ git reset HEAD test.py
    
配置一个git last,让其显示最后一次提交信息:
    $ git config --global alias.last ‘log -1‘
这样,用git last就能显示最近一次的提交:
    $ git last
    commit adca45d317e6d8a4b23f9811c3d7b7f0f180bfe2
    Merge: bd6ae48 291bea8
    Author: Michael Liao <askxuefeng@gmail.com>
    Date:   Thu Aug 22 22:49:22 2013 +0800

    merge & fix hello.py

甚至还有人丧心病狂地把lg配置成了:
git config --global alias.lg "log --color --graph --pretty=format:‘%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset‘ --abbrev-commit"

配置文件
配置Git的时候,加上--global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。
配置文件放哪了?每个仓库的Git配置文件都放在.git/config文件中:
$ cat .git/config
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[remote "origin"]
    url = git@github.com:michaelliao/learngit.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
    remote = origin
    merge = refs/heads/master
[alias]
    last = log -1

别名就在[alias]后面,要删除别名,直接把对应的行删掉即可。
而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中:
$ cat .gitconfig
[alias]
    co = checkout
    ci = commit
    br = branch
    st = status
[user]
    name = Your Name
    email = your@email.com
配置别名也可以直接修改这个文件,如果改错了,可以删掉文件重新通过命令配置。
7.4 大家git服务器
   教程中介绍的使用linux服务器。这一节没有实战 教程地址:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137586810169600f39e17409a4358b1ac0d3621356287000

廖雪峰Git教程学习笔记