[关闭]
@ValenW 2016-05-05T22:13:30.000000Z 字数 6081 阅读 1830

Git简易教程

博客 作业 教程


Linus在1991年创建了开源的Linux,由于有众多网友贡献代码,管理代码成为了一个问题。在2005年,Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git。Git迅速成为最流行的分布式版本控制系统,在2008年,GitHub网站上线,为开源项目免费提供Git存储。


目录

安装与使用

Linux

  1. $ sudo apt-get install git
  2. $ git

Mac OS X

本人没有实际操作过,以下来自廖雪峰老师的教程

直接从AppStore安装Xcode,Xcode集成了Git,不过默认没有安装,你需要运行Xcode,选择菜单“Xcode”->“Preferences”,在弹出窗口中找到“Downloads”,选择“Command Line Tools”,点“Install”就可以完成安装了。

Windows

msysgit
国内镜像
安装完成后,在开始菜单里找到Git -> Git Bash,会产生个命令行界面,这就是Windows下的git

配置账户:

  1. $ git config --global user.name "username"
  2. $ git config --golbal user.email "email@you.com"

gitHub Desktop

一个有友好UI界面的Github客户端,没有需复杂命令行,可运行在Windows和Mac OS X系统下。
GitHub Desktop - Simple collaboration from your desktop

git和github?

git是一个分布式版本控制软件,最初由林纳斯·托瓦兹(Linus Torvalds)创作,于2005年以GPL发布。而GitHub是一个利用Git进行版本控制、专门用于存放软件代码与内容的共享虚拟主机服务。它由GitHub公司(曾称Logical Awesome)的开发者Chris Wanstrath、PJ Hyett和Tom Preston-Werner使用Ruby on Rails编写而成。

集中式版本控制和分布式版本控制?

主要在于工作时是否需要保证当前的代码版本为最新版,这需要一台中心服务器,并且工作中的每台电脑都必须要联网。而分布式则没有这些要求,每个人都会有一份完整的代码仓库的拷贝,离线工作完成后,只要交换各自的更改,处理冲突,达成一致后就能有一份最新的版本。具体参考廖老师的教程

版本库控制

版本库是记录文件或目录状态的地方,存储着内容修改的历史记录。可以简单理解成一个目录,这个目录下所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

创建

在本地创建一个空版本库:

  1. $ cd dir/of/repository
  2. $ git init

克隆本地版本库:

  1. $ cd father/dir/of/repository
  2. $ git clone /path/to/repository

克隆远程版本库:

  1. $ cd father/dir/of/repository
  2. $ git clone /path/to/the/remote/repository

或者

  1. $ git clone git@github.com:username/repo-name.git

比如:

  1. $ cd ~
  2. $ git clone https://github.com/ValenW/AQL-Subset
  3. $ cd AQL-Subset

提交变动到版本库

git的本地仓库通过维护.git文件夹里的版本库记录来维护版本库。其中有称为stage的暂存区,自动创建的master分支和指向当前版本的HEAD指针。
添加文件改动到版本库需要分两步,add和commit。add指令将所要提交的修改放到暂存区(stage),可以多次add,而commit指令将缓存区中所有变动一次性提交到版本库中。

add

编辑好文件,比如new_file.txt, 之后将文件放入到版本库目录下,然后$ git add new_file.txt即可。
若要把版本目录下所有文件都加入到版本库,则只需$ git add *即可

commit

$ git commit -m "message about this commit"其中-m后面输入这次提交的详细说明。
这样就完成了一次代码库的变动提交

rm

$ git rm filename会将filename删除,并提交该修改到缓存区,之后可用过$ git commit来提交这次删除操作。

查看当前代码库状况

$ git status命令会显示当前代码库的状况,包括添加,修改(modified),删除(deleted)
$ git diff filename命令可以查看某个文件的具体内容变动,格式是标准的Unix通用diff格式

查看提交的历史记录

使用命令$ git log
如果信息太多,可以在一行内展示一次提交:$ git log --pretty=online
更多格式化可参考这篇文章,一个丧心病狂的命令就是git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset' --abbrev-commit --date=relative

版本管理

指向git当前最新版本为HEADHEAD^表示上一版本,HEAD^^上上一个版本,HEAD~100表示往上100个版本

版本标签

可以对某次提交打上如v0.3之类的标签。
git tag <tag-name> <branch-id>branch-id对应的分支打上标签,如空则默认为当前分支打上标签。
git tag -a <tag-name> -m "tag-massage"可以指定标签名和对应信息。
之后可通过git show <tag-anme>获取具体信息。
git tag -d <tag-name>删除对应标签。

提交标签到远程仓库

git push origin <tag-name>推送tag-name到远程仓库
git push origin --tags推送所有未推送的tag到远程仓库
git push origin :refs/tags/<tag-name>删除远程标签,之前必须删除本地对应标签。

版本回退

要回退到某一版本时,比如上一版本,只需$ git reset --hard HEAD^
那回退后后悔了,要回退到更新的版本呢?可以通过commit id或者标签来标识某一版本:

  1. $ git reset --hard commit_id

commit id可以在git log命令中找到,只需输入前几位,保证唯一就可以了,不必写全。
git reflog则会把reset也作为一次更新,这样就可以找到所有版本的id了。

缓存区回退

$ git reset HEAD filename命令可以将缓存区中的所有修改撤销掉,并将修改放回工作区中,如此时工作区原本有修改,则会被覆盖。

工作区回退

git checkout -- filename可以撤销工作区中filename的修改,将其回退到最近一次git commitgit add时的状态

撤销总结

  1. 修改后 未add(添加到暂存区)
    • git checkout -- myfile.txt 或 手动删除工作区修改
    • 工作区 : clean 暂存区: clean
  2. 修改后 add了(未commit) 再次修改文件 要撤销第二次修改时:
    • git checkout -- myfile.txt (将暂存区恢复到工作区)
    • 暂存区有第一次的修改需要commit
  3. 修改后 add了(未commit),需要撤销修改时:
    • git reset HEAD myfile.txt (将暂存区修改删除)
    • 此时工作区的修改还未撤销
    • git checkout -- myfile.txt (撤销工作区修改)
  4. 修改后 add并commit了,需要撤销修改时:
    • git reset --hard HEAD^ (版本回退)

远程版本库控制,以github为例

关联用户主机和Github账号

创建用户的SSH Key(在shell或git bash内):
$ ssh-keygen -t rsa -C "email@you.com"
在github上添加SSH KeyGithub添加SSH Key

将本地仓库关联到远程仓库

在本地仓库的目录下
$ git remote add origin git@github.com:username/repo-name.git
第一次提交:
$ git push -u origin master
以后:
$ git push origin master

分支管理

创建分支

$ git checkout -b br-name
相当于

  1. $ git branch br-name
  2. $ git checkout br-name

$ git branch会显示出所有分支,当前分支前会有*标记

合并分支

$ git merge br-namebr-name分支合并到当前分支下
加入--no-ff则表示禁用Fast forward模式。即新建commit而不是切换HEAD指针来实现
$ git merge --no-ff -m "merge with no-ff" dev
合并分支前可以通过git diff <source_branch> <target_branch>来查看两者不同

删除分支

$ git branch -d br-name

冲突解决

merge分支时,如果两分支对同一地方做了不同的修改,则为冲突,冲突的文件git会生成如下内容

<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> feature1

则直接在产生的文件中修改,然后add,commmit即可

git log --graph可以看到分支合并图

bug修复,临时分支

需要修复bug,但当前任务没完成,可以用stash来存储现场。

保存

git stash保存当前工作现场,之后就可以放心转去bug分支修复bug,之后再回来。git stash list命令可以看到当前的stash列表。

恢复

git stash apply可以恢复最近一次的现场,但恢复后不删除stash list中的stash,之后需要使用git stash drop来手动删除。
也可以直接git stash pop来恢复同时删除现场。
更详细的可以参考廖雪峰教程

feature分支

同样的做法也可以用于新增feature。增加新功能前先在最新代码上新建一个分支,完成后再和整体代码合并。

多人协作模式

pull和关联本地和远程代码库

首先,需要从github上pull项目代码,然后将本地代码和远程代码关联起来,参考创建版本库和关联本地和远程代码库两章。
可用git remotegit remote -v显示详细信息。
clone后默认只看得到master分支,可用git checkout -b branch-name origin/branch-name来创建和远程分支对应的本地分支。

推送修改

需要推送自己的修改时,用git push origin <branch-name>来推送自己的修改。
如果推送失败,则是因为远程分支比你的本地更新,需要先用git pull试图合并远程和本地的代码。
如果合并有冲突,则解决冲突,并在本地提交。
没有冲突或者解决掉冲突后,再用git push origin <branch name>推送。
如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to origin/branch-name branch-name进行关联。

github下的协作

先fork仓库到自己账户下,自己完成修改后提出"pull request",等待对方接受。

其他

.gitignore文件

每一行是一个规则,目录下匹配的文件会被git忽略。可以使用正则表达式语法,Github已经提供了常用环境和语言的范例文件
如果出现add时因为ignore文件而无法添加,则可以使用-f强制添加:$ git add -f a.cpp,如果是ignore规则有问题,则$ git check-ignore -v a.cpp命令可以查看是哪条规则导致无法添加

别名

$ git config --global alias.st status执行后就可以用st代替status
或者这么用

  1. 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"

然后log界面就成这样了:
log配置界面

其他参考资料

git 教程

Github功能

Issue

基本功能和讨论版一样,有标题和正文,支持Markdown语法。主要用于提出需求,报告bug,讨论实现等等。嗯,也有人用Issue来写博客。

Milestones 里程碑

每个issue可以被包括在某个里程碑上,比如版本更新,alpha,beta版本等等。这样就可以通过里程碑来查找有哪些讨论。

label 标签

每个issue都可以被打上标签,如bug,feature等。github默认有几个标签,当然也可以自定义标签。

@ 提及

在issue中可以用@username来提及某个用户,这样该用户就可以收到提醒。
通常用法是/cc @user1 @user2 /cc表示carbon copy,副本。

references 涉及

在issue正文中可以通过#issueId来提及某个特定的issue,表示这个讨论和提及的讨论有关。
并且,在commit代码的时候,在提交说明中也可以用#issueId提及某个issue,如果检测到说明中含有“Fixes”, “Fixed”, “Fix”, “Closes”, “Closed”, “Close”关键字,则对应issue会被关闭。

详细可参考官方文档:Mastering Issues

wiki

呃就是个写wiki的功能,无法自动生成,全都要自己手写,可以有标题,分页,目录等功能,支持markdown等语法
官方文档:Mastering Wiki

其他链接:
Github Octocat
Github emoji

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注