项目版本控制工具-git
2016年05月26日

概述

Git是一个开源的分布式版本控制系统,用以有效、高速的处理从很小到非常大的项目版本管理。

基本配置

用户名

git config --global user.name "Your Name"

email

git config --global user.email you@example.com

如果需要使用其他的编辑工具来编辑提交版本的描述,可以使用以下命令

git config --global core.editor EDITOR_NAME

忽略文件mode变更
最近在windows不同电脑之间同步时候,发现总会出现mode变更问题,可以用一下配置忽略
出现这种问题的原因还是因为多个计算机上相同文件的用户组/用户名 id不一致造成的

git config --global core.fileMode false

git代理设置

git config --global http.proxy http://127.0.0.1:8087
git config --global http.sslverify false
git config --global https.proxy http://127.0.0.1:8087

git修改push/pull 的默认分支

git branch --set-upstream-to=origin/dev dev

origin为远端的服务器别名 dev为分支名

常用命令

命令 含义
git init 初始化git信息,创建git环境
git log 显示版本日志
git log -p 显示版本的具体修改 后边可以跟各种节点,ip等信息.方便缩小范围
git status 显示当前版本的具体状态 文件变更
git diff 显示当前修改与上一个版本的差异
git add <file/directory> 添加文件或者目录到现在的版本中

一般在项目的根目录使用git add .,这样git会自动递归添加项目的所有增加/删除变动到本次做的版本当中
为了让git add .能够忽略一些文件的修改,可以修改项目目录下的.gitignore文件,在里边添加要忽略的文件名或者扩展名,每行一个

git rm file                 #从当前版本中删除文件
git rm -r --cached dir1     #从当前版本中删除文件夹dir1 如果想同时删除这个目录,可以把--cached参数换成-f
git commit                  #提交当前的操作,完成一个新的版本
-a                          #自动跟踪已经添加的文件变更
-m "描述"                   #版本描述
-v                          #调用git diff显示本次版本的具体差异

如果不添加 -m "" 参数,git会调用$EDITOR请求输入版本描述信息

git reset --hard HEAD~          #删除上一个版本
git push                        #提交更新
git push --force origin master  #提交远端更新的master分支

git clone https://xxxxxxxx              #克隆远端的项目
git clone git@github.com:xxx/xxxx.git   #克隆远端的项目
git remote add origin user@host:/path/of/git/project.git    #设置远端git仓库
git fetch origin master                 #从远端获取origin仓库的master分支,也可以忽略master,默认为master
git remote -v                           #显示远端项目的所有仓库

基本流程

git 是以项目为单位,进行版本控制的软件.而区分项目的方式,就是文件夹,所以需要先创建一个文件夹

mkdir $HOME/pro             #创建项目文件夹
cd $HOME/pro
git init                    #初始化项目
touch README                #创建说明文件,github.org默认使用这个名字
git status                  #查看当前的版本状态
git add README              #把README添加到当前版本中
git commit -m "第一个版本"  #提交一个版本
git log                     #查看版本日志

第二次修改文件,需要同样的添加文件到当前版本,然后再提交版本.可以利用git log -p查看具体修改细节,git会调用diff命令,显示修改细节.可以查看diff.

echo "hello" >> README
git add README
git commit -m               "在README文件中添加一些描述"
git log -p                  #查看项目版本的具体修改细节

为了简化git add FILEgit rm FILE等操作,可是使用git commit -a的方式,让git自动跟踪文件修改和删除.但是-a参数只会跟踪那些已经被跟踪的文件的修改或者删除操作.

git commit -a 

可以利用git diff命令检索当前的文件和上一个版本的区别,如果输入文件,来明确指出查看某一个文件的区别,或者不指定文件,来显示所有文件的区别

git diff [file]

为了简化git的操作,可是使用类似shell alias的方式,进行缩写.

git config --global alias.ci "commit -a -v"             #提交更改并显示差异
git config --global alias.throw "reset --hard HEAD"     #恢复到当前版本的初始状态
git config --global alias.throwh "reset --hard HEAD^"   #恢复到上一个版本的状态
git config --global alias.br "branch"                   #显示分支

所有有关git的全局配置会存放到$HOME/.gitconfig文件中

cat $HOME/.gitconfig

git ci              #提交更改并显示差异
git br              #显示分支列表
git br -D tmp       #删除tmp分支

创建版本控制忽略的文件列表,忽略的文件不会被版本差异追中

echo *.log > .gitignore

如果想取消本次版本的修改,可以使用git reset --hard HEAD命令,但需要注意git只会回滚已经被跟踪的文件,对于新创建但还没有被add的文件,git不会删除.

echo hello > newfile1 > newfile2
git add newfile1
git reset --hard HEAD   

由于当前版本只添加了newfile1,所以只会删除newfile1,而newfile2由于还没有添加(add)到当前版本,所以git不会删除它

对于项目控制上,如果只是想单独的回滚某个文件的修改,可以使用git checkout file命令

echo hello > file1
git add file1
echo 111 >> README
git checkout 


git reset --hard HEAD~1     #删除上一个提交的版本 

git stash 隐藏当前的修改
git stash apply 回复之前的修改

临时隐藏(挂起)之前的修改,来修复某个单独的文件

echo 100 > a 
echo 23 > b
git add .
git commit -a -m "版本1"

假设需要把a文件的内容改成1,但是突然发现b文件的内容也有错误,需要修改.可是先这样做

echo 1 > a
git stash   #隐藏此次修改
echo 2 > b  #修复小的错误
git commit -a -m "修复b文件的错误"
git stash apply #恢复之前的隐藏
git commit -a -m "更新a文件的内容"

及由这种方法,可以临时隐藏当前版本的修改,然后去单独修复某个小bug,提交版本后,再恢复之前内容.可是说为了处理这种小问题而设计的功能.
也正因此,git stash所隐藏的文件变更,最好不要再恢复隐藏前修改他们.否则git stash apply恢复的时候,会将隐藏和修改的内容都追加到文件当中.

有关分支的控制

git checkout -b "BRANCH_NAME"   #创建一个分支
git checkout COMMIT_ID -b "BRANCH_NAME" #创建指定版本的分支,创建指定版本的分支,可以只输入最少前4位id就可以,但是要保证前4位必须是唯一的 
git checkout "BRANCH_NAME"      #切换分支
git branch -D "BRANCH_NAME"     #删除分支

同步更新
git clone url
例如:

git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle

注意:
1>必须有协议头 https://
2>要下载的项目名字区分大小写

创建新仓库

touch README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin git@github.com:cnfczn/fivefishflash.git
git push --set-upstream [nickname] [branchname]
git push -u origin master

向一个已经存在的仓库push

git remote add origin git@github.com:cnfczn/fivefishflash.git
git push -u origin master

如果出现没有pull权限的提示

ssh-keygen -t rsa 三下回车
cd ~/.ssh/
cat id_rsa.pub

打开github.com->帐号设置->ssh-key->添加新key->复制id_rsa.pub内容
重新pull

简单创建 上传

touch README.md
git init 
git add .
git commit -m "first commit"
git remote add origin git@github.com:cnfczn/cnfczn.github.io.git
git push --force origin master

git ssh 连接设置

github ssh密钥配置向导

检查已经存在的ssh key

cd ~/.ssh
ls -al

检查文件夹内是否有id_rsa.pub或者id_dsa.pub文件.如果没有就执行第二步,有的话就跳过第二步

生成 ssh key

ssh-keygen -t rsa -C "your_email@example.com"

注意替换邮箱地址,提示输入密码不用管.直接按回车就可以

添加新的key到 ssh-agent

ssh-add  ~/.ssh/id_rsa

把ssh key添加到github里

打开github->Account settings->SSH Keys->Add SSH key

cat .ssh/id_rsa.pub 

粘贴id_rsa.pub文件所有内容到key文本框,取个名字就可以保存了

测试

ssh -T git@github.com

大致提示,ssh功能已经验证成功,但是github不提供shell访问,就说明已经配置完成了!

服务器端git仓库设置

创建git用户

useradd -m git

为了安全考虑,ssh只允许密钥链接,并且修改默认端口

创建现有项目的裸仓库(中心仓库)

$ git clone --bare project1 project1.git
Cloning into bare repository 'project1.git'...
done.

将裸仓库传到服务器上

scp -P <port> -r project1.git user@git.example.com:/path/of/git_repo_dir
scp -P 9999 -r project1.git git@hostname:/path/of/save/dir

将裸仓库传到服务器上,这里注意,提前做好ssh key的验证以及端口设置
上传完成,本地的.git裸仓库就可以删除了rm -rf project1.git

为现有仓库设置远程服务器地址

git remote add hostname ssh://git@hostname:9999/path/of/git/project.git

远程服务器帐号git,主机名、端口、路径 ,注意是从根目录开始的绝对路径

克隆仓库

对于本地重新克隆远端仓库,直接使用clone命令就可以了,不需要设置远程服务器地址

git clone ssh://git@hostname:9999/path/of/git/project.git

提交更改

git add .
git commit -m "xxx"
git push

常见问题

windows 无法添加私钥

在linux下,正常使用ssh-add 添加私钥,但是在windows下却会报错
ssh-add path/of/id_rsa报错,提示:
Could not open a connection to your authentication agent.

解决办法

ssh-agent bash
ssh-add "C:\Users\Administrator\.ssh\id_rsa"
ssh -l [username] -p [port] [ip_address]

解决远程与本地版本冲突

昨天发现了一个新的前端框架Semantic UI,觉得比较新奇嘛,于是乎就动手做一个页面试试,在晚上11点左右页面做好了并上传到GitHub,开启了pages.今天上午发现手机上显示有问题,修改了代码,准备再次Push到GitHub上的时候,问题出现了:

To ssh://hostname:9999/path/of/git/project.git
! [rejected]        master -> master (fetch first).
error: failed to push some refs to 'ssh://git@hostname:9999/path/of/git/project.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

看到这提示,我马上打开GitHub查看了一番,发现GitHub在给pages添加域名时,创建了一个CNMAE的文件.远程有了更新而本地也有了更新,怎么办呢?我的做法是这样的.
解决方法

  1. 把远程仓库master分支下载到本地并存为tmp分支
    git fetch origin master:tmp
  2. 查看tmp分支与本地原有分支的不同
    git diff tmp
    这里主要是看看有没有其他的改动…
  3. 将tmp分支和本地的master分支合并
    git merge tmp
    这个时候呢,本地与远程就没有冲突了,而且还保留了我今天的代码,现在Push就OK啦!
  4. 最后别忘记删除tmp分支
    git branch -d tmp
    哈哈,又可以快乐的coding啦