学习资料:

http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000

http://codingnow.cn/version/212.html

http://blog.jobbole.com/34503/

http://www.cnblogs.com/lwzz/archive/2013/02/23/2921426.html

 

Git即集中式版本控制系统。mac上的安装:直接从AppStore安装Xcode,Xcode集成了Git,选择菜单“Xcode”->“Preferences”,在弹出窗口中找到“Downloads”,选择“Command Line Tools”,点“Install”就可以完成安装了。

1.版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

  • 初始化一个Git仓库,使用git init命令。
  • 更新一个Git仓库,即添加文件到Git仓库,分两步:  (add放到暂存区(stage),commit放到工作区)
    • 第一步,使用命令git add <file>,注意,可反复多次使用,添加多个文件;
    • 第二步,使用命令git commit,完成。   -m “xxx” 本次提交的说明。Git跟踪并管理的是修改,而非文件,表现在git commit只负责把暂存区的修改提交了。
  • 查看仓库状态,即距离上个更新版本有哪些更改。
    • git status哪些文件更改了(有没有放到暂存区也显示)。一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的.
    • git diff <file>更改了什么。
  • 查看仓库更新的历史纪录,git log命令显示从最近到最远的提交日志,可以看到3次提交。
  • 到指定版本:
    • HEAD表示当前版本,HEAD^是上一个版本,HEAD^^是上上一个版本,HEAD~100往上100个版本。 

 git reset --hard HEAD^     回退到上一个版本“add distributed”

    • 通过版本号(hash id)转到某一版本。版本号没必要写全,前几位就可以了,Git会自动去找。
git reset --hard 3628164
    • Git提供了一个命令git reflog用来记录你的每一次命令。可以通过此找到版本号回到“未来版本”。 

Ps:Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD修改指针,同时更新工作区。

  •  git checkout --  <file>   让这个文件回到最近一次git commitgit add时的状态。  没有--,就变成了“创建一个新分支”的命令
  • 与add对应,rm是删除某文件,也要commit生效。撤销删除可以用checkout --

 

 

2.远程仓库

只有一台机器有一个原始版本库,此后,别的机器可以“克隆”这个原始版本库,而且每台机器的版本库其实都是一样的,并没有主次之分。

找一台电脑充当服务器的角色,每天24小时开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。

由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置:

  • 创建SSH Key。 
  • 登陆GitHub添加SSH Key。

1)使用remote add把本地仓库的内容关联到远程仓库(至少先创建个空到远程仓库)。

$ git remote add origin git@github.com:<git账户名>/<本地仓库名>.git

添加后,远程库的名字就是origin,这是Git默认的叫法。

使用命令push第一次推送master分支的所有内容,以后再push不需要加-u。

git push -u origin master

 2)先有远程库,然后,从远程库克隆。

git clone git@github.com:<git账户名>/<远程仓库名>.git

地址还可以是https://github.com/michaelliao/gitskills.git这样的地址,支持ssh和http两种协议。

git clone默认会把远程仓库整个给clone下来,但只会在本地默认创建一个master分支 

 

3.分支

分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。

现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。

1)

  • 每个节点是一次commit,用时间线链接起来,分支其实是指向节点的指针,创建、切换、合并、删除分支等操作其实都是在操作指针。
git checkout -b feature1  //创建一个新分支feature1并切换
git checkout master     //切换回maseter
  • 当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。git status可以告诉我们冲突的文件。可以直接查看冲突文本,Git用<<<<<<<=======>>>>>>>标记出不同分支的内容。
git merge feature1
git status
git add readme.txt 
git commit -m "conflict fixed"              
git log --graph --pretty=oneline --abbrev-commit    //用带参数的git log可以看到分支的合并情况
git branch -d feature1         //删除分支feature1

  合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

git merge --no-ff -m "merge with no-ff" dev
  • 分支策略

首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;

那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;

你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。

    • 修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。

    • 开发一个新feature,最好新建一个分支;如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。

 

2)与远程仓库关于分支的交互

  • 查看远程库信息,使用git remote -v;查看branch信息, git branch -a;

  • 本地新建的分支如果不推送到远程,对其他人就是不可见的;

  • 从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;

git push --all origin
git push <远程主机名> <本地分支名>:<远程分支名>
    • master分支是主分支,因此要时刻与远程同步;
    • dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
    • bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
    • feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
  • 在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;

  • 建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name

  • 从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。

git pull <远程主机名> <远程分支名>:<本地分支名>

 

 

 

 

手册:

  • git help <命令> 可以看doc。
  • The most commonly used git commands are:

   add        Add file contents to the index

   bisect     Find by binary search the change that introduced a bug

   branch     List, create, or delete branches

   checkout   Checkout a branch or paths to the working tree

   clone      Clone a repository into a new directory

   commit     Record changes to the repository

   diff       Show changes between commits, commit and working tree, etc

   fetch      Download objects and refs from another repository

   grep       Print lines matching a pattern

   init       Create an empty Git repository or reinitialize an existing one

   log        Show commit logs

   merge      Join two or more development histories together

   mv         Move or rename a file, a directory, or a symlink

   pull       Fetch from and integrate with another repository or a local branch

   push       Update remote refs along with associated objects

   rebase     Forward-port local commits to the updated upstream head

   reset      Reset current HEAD to the specified state

   rm         Remove files from the working tree and from the index

   show       Show various types of objects

   status     Show the working tree status

   tag        Create, list, delete or verify a tag object signed with GPG