Git基础
1.Git:分布式的版本控制系统
分布式和集中式最大的区别就是它没有中央服务器这么一说,每台电脑都是一个服务器,每台电脑都拥有一个完整的版本库,谁修改了就把新的数据推送到其他电脑上,如果某台电脑挂掉了,没事,从别的电脑上拷贝一个出来就搞定
Git 操作命令
git init --- 使用当前目录作为Git仓库
git init newrepo --- 使用指定目录作为Git仓库
初始化后,会在新建的仓库下出现一个.git的目录,所有 Git 需要的数据和资源都存放在这个目录中
eg:
mkdir test
cd test
git init
将文件加入版本库,使用 git add 命令告诉 Git 开始对这些文件进行跟踪,然后提交
$ git add *.c --- 将 .c 结尾的文件全部新增到版本库
$ git add README
$ git commit -m '初始化项目版本' --- 提交文件时,一定要加 -m 操作说明
$ git add --- 添加当前项目的所有文件,将想要快照的内容写入缓存区
git clone <repo> --- 从git仓库中拷贝项目
git clone <repo> <directory> --- 从git仓库中拷贝项目到指定目录
eg:
$ git clone git://github.com/schacon/grit.git
$ git status <-s> --- 查看项目的当前状态
$ git commit --- git add 是将想要快照的内容写入缓存区,git commit将缓存区内容添加到仓库中
$ git commit -a --- 直接提交目录下已修改的文件到仓库
$ git reset HEAD -- filename --- 取消已缓存的内容 filename
2.Git基础
1.安装Windows下的Git后,出现2个启动程序:
Git Bash Unix Shell命令窗口
Git GUI Windows操作界面
2.设置全局的用户名和Email --- 打开Git Bash
git config --global user.name "Jay"
git config --global user.email "jayhe@qq.com"
3.Git 基本概念
分支(branch) 一个分支,即:一个独立拥有自己历史版本信息的代码线,可以从已有代码中生成一个新分支,这个分支与其余的分支完全独立。
默认分支叫 master, 用于可以选择一个分支,选择一个分支叫 Checkout
提交(commit) 提交更改到Git库中,它将创建一个新的提交对象,这个提交对象会有一个新版本的唯一标识,本次修订后,可以检索(eg:查看旧版本源码),
每个提交对象中都会包含修改者和提交者,修改者和提交者可以是不同的人
头(HEAD) 象征性的参考,最常用以指向当前选择的分支
仓库(Repository) 仓库包含了随着时间推移和各种不同的分支和标签不同版本历史,
在Git仓库的每个副本是一个完整的信息库。你可以从仓库中获取你的工作副本。
修订(Revision) 表示代码的一个版本状态
标记(Tags) 某个分支某个特定时间点的状态,通过标记,可方便的切换到标记时的状态
URL 仓库所在位置
工作区(Working Tree) 工作区包含了仓库的工作文件,可以修改的内容和提交更改作为新的提交到仓库
暂存区(Staging area) 工作区用来提交更改(commit)前可以暂存工作区的变化,工作区未commit之前的改变
暂存区包含了工作区的一系列更改快照,这些快照可以用来创建新的提交
索引(Index) 索引是暂存区的另一种术语。
工作区,暂存区,版本库的关系
工作区 -- 添加选择的改变 ( git add ) --> 暂存区 -- 提交改变 ( git commit ) --> 版本库
4.常用的Git指令
add 添加文件到索引(暂存区)
branch 列出、创建、删除分支
checkout 从仓库拉取代码到工作区
clone 克隆一个仓库到指定目录
commit 提交更改到仓库
diff 查看两次提交,或工作区直接的不同
fetch 从另一个仓库下载内容
init 创建一个空的Git仓库,或重新初始化一个已存在的Git仓库
log 查看提交日志
merge 合并分支
pull 拉取更新
push 推送更新
rebase 主要用在从上游分支获取最新commit信息,并有机的将当前分支和上有分支进行合并 参考:http://gitbook.liuhui998.com/4_2.html
reset 回退到某个指定版本
status 查看工作区状态
tag 列出、创建、删除 标识tag
5.常见的Git操作
1.仓库操作
1.创建仓库
#进入d盘目录
$ cd /d
#创建JackyGit文件夹
$ mkdir JackyGit
#进入JackyGit文件夹
$ cd JackyGit
#显示当前所在路径
$ pwd
#初始化当前目录作为Git仓库
$ git init
Initialized empty Git repository in d:/JackyGit/.git/
2.添加文件到仓库 -- 先进入仓库
mkdir jay
cd jay
touch test.txt #创建文件
echo test > test.txt #写入内容
3.查看Git仓库状态
git status
4.增加文件到暂存区
#增加所有文件到暂存区
git add .
说明: add . 将当前路径所有文件都提交到暂存区
add file 将指定文件提交到暂存区
5.提交更改
--- git commit -m "提交信息"
git commit -m "init files"
6.再次查看状态
$ git status
On branch master
nothing to commit, working directory clean
2.操作项目
1.查看操作日志
$ git log
commit 162aac88fef714a1ad60b0c98f040163dd895f5f
Author: Jay He <871825513@qq.com>
Date: Thu Nov 3 15:08:05 2016 +0800
init Files
2.修改项目内容
$ echo "Hello Test" > test1.txt
3.查看当前状态
$ git status
On branch master
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: test1.txt
4.提交修改
--- git commit -a -m "提交信息" 该命令,可省掉放入暂存区的操作,注解提交
$ git commit -a -m "直接提交"
5.查看操作日志
$ git log --pretty=oneline #单行显示,只显示版本号和备注
62d298b578aea3429617e0610b50329004479eaf 直接提交
162aac88fef714a1ad60b0c98f040163dd895f5f init Files
6.比较版本 --- git diff 用于比较上次提交和当前版本的差异
#修改本地版本的内容
$ echo "HelloGit" > test.txt
#使用git diff查看差异,可以看到testtest被删除了,而HelloGit被添加了
$ git diff
diff --git a/jay/test.txt b/jay/test.txt
index 5b3b4a7..84fab2a 100644
--- a/jay/test.txt
+++ b/jay/test.txt
@@ -1 +1 @@
-testtest
+HelloGit
7.提交修改,并打开Git GUI界面
#提交所有修改
$ git add . && git commit -m "提交修改"
#打开GUI界面
$ gitk --all
8.修改提交信息
--- git commit --amend -m "修改的提交信息" : 修改上次提交的信息
git commit --amend -m "修改了上次提交的信息"
9.删除项目内容
rm data01
git add . && git commit -m "删除了test1.txt"
3.版本管理
1.版本回退
#查看从项目开始到现在做了什么操作
$ git log --pretty=oneline
e5da0b55510ef348ba96398be7978fca7751feed delete test1
6f6575694f931a3b509dd0a01af095495df9b089 delete test1.txt
04e8999e0281998c508e110b51d71827a0e28a00 删除
3e2356cc9babadd7e0b81c228c1340fe3421401b 修改了上次提交的信息
62d298b578aea3429617e0610b50329004479eaf 直接提交
162aac88fef714a1ad60b0c98f040163dd895f5f init Files
如果不想移除 test1.txt了,可用git reset进行版本回退,
git用HEAD表示当前版本,HEAD^,表示上一个版本,HEAD^^表示上上一个版本,HEAD~100表示往前100个版本
#回退到上一个版本
$ git reset --hard HEAD^
#回退到这之前的第2个版本
$ git reset --hard HEAD~2
说明:
1.--hard参数,会把源码也给推送到指定版本,不用--hard,源码不会修改,只会回退,
即:--hard会用指定版本覆盖现有源码,而不用--hard,源码不会更改,只是回退
2.reset只对本地仓库有效,对远程仓库无效
如何回退远程版本?
1.先不要在本地reset,而是先创建一个分支old_master,并切换到old_master分支
2.push old_master分支到远程仓库
3.在old_master分支上reset版本,并删除本地的master分支和远程的master分支
4.创建本地分支master,推送到远程分支master,此时远程分支会新建master
5.删除本地old_master分支和远程old_master分支
注意:以上操作较危险,谨慎处理!!!
2.版本选择
--- git reset --hard 版本号
eg:
#查看版本提交信息
$ git log --pretty=oneline
7e0b3a80e57d32b703681f7da332febeb2dc8d59 test1
62d298b578aea3429617e0610b50329004479eaf 直接提交
162aac88fef714a1ad60b0c98f040163dd895f5f init Files
#选择第一个版本
$ git reset --hard 7e0b3a80e57d32b703681f7da332febeb2dc8d59
HEAD is now at 7e0b3a8 test1
注意:
版本号可用不用完全输入,输入前几个git就会帮你找到,也不能太少,太少可能会找出多个
提醒:
如果git bash被关掉了,找不到版本号,可用 git reflog查看每一次的操作记录
#显示每次操作记录,然后就可以用reset所以选择版本了
$ git reflog
3.撤销修改
1.工作区 git checkout -- file 撤销对文件file的改动(修改、删除)
#修改test.txt内容
$ echo "Bye SVN" > test.txt
#查看git状态
$ git status
#想撤销修改、删除
$ git checkout --file test.txt
2.暂存区
必须先使用git reset HEAD file 把暂存区的修改撤回到工作区的修改,
然后再执行工作区的撤销修改操作 git checkout -- file
#修改test.txt内容
$ echo "Bye SVN" > test.txt
#提交到暂存区
$ git
$ git checkout --file test.txt
3.已提交到版本库
使用reset回退功能即可
4.远程仓库操作
--- 远程仓库:用来把Git仓库托管到互联网,本地网络或本机中
0.Github远程仓库操作
参考:http://www.cnblogs.com/tugenhua0707/p/4050072.html
1.创建SSH Key , 在用户主目录下,生成 .ssh 目录,包含id_rsa(私钥)和id_rsa.pub(公钥)这两个文件,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人
ssh-keygen -t rsa -C "871825513@qq.com"
注意:
如果本机已经存在 .ssh ,可以在创建时,选择一个密钥文件,用于存放公钥和密钥
2.添加SSH Key到github
登录github,打开sittings中的SSH Keys页面,点击 New SSH Key,填上任意title,在Key文本框里黏贴id_rsa.pub文件的内容
3.添加远程仓库
将本地的Git仓库和github上创建的Git仓库进行远程同步,样github的仓库可以作为备份,又可以其他人通过该仓库来协作
1.登录github,新建仓库 --- 右上角(+),点击 "New repository",新建仓库
在Repository name填入gittest1,其他保持默认设置,点击“Create repository”按钮,就成功地创建了一个新的Git仓库
注意:
在github上,新创建的gittest1仓库是空的,
可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub仓库
2.关联本地git仓库和github仓库 --- 这里关联本地的 jay仓库 和 gittest1仓库
进入本地jay仓库,执行命令
$ git remote add origin https://github.com/jayfeihe/gittest1.git
说明:
每个github仓库都有独立的github地址:1.HTTPS 2.SSH
3.推送本地库内容到远程仓库 --- 把本地master分支的最新修改推送到github上
$ git push origin master
4.从远程仓库克隆 --- 使用HTTPS地址
$ git clone https://github.com/jayfeihe/gittest1.git
5.提交本地文件到远程仓库
eg:
#创建新文件
$ touch remote.txt
#提交给工作区
$ git add .
#提交到本地库
$ git commit -m "commit to local repository"
#推送到远程库
$ git push https://github.com/jayfeihe/gittest1.git
注意:
推送给github仓库时,需要填写github的账户密码
1.创建本地远程仓库 git clone --bare
#1个点表示当前目录,2个点表示父目录 --- 为demo1仓库,建立一个本地远程仓库demo2
$ git clone --bare . ../demo2/remote-demo1.git
Cloning into bare repository '../demo2/remote-demo1.git'...
done.
2.推送更新到远程仓库
参考:
http://blog.csdn.net/column/details/jacky-git.html
http://www.cnblogs.com/itech/p/5188932.html
http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000
3.添加远程仓库
4.查看远程仓库信息
5.克隆仓库
6.Push(推送更新)和Pull(拉取更新)
7.移除远程仓库
5.创建和合并分支
分支: Git把每次提交都串成一条时间线,这条时间线就是一个分支
主分支:默认的Git分支,又叫 master分支
HEAD严格来说不是指向提交,而是指向mater,master才是指向提交的,HEAD指向的就是当前分支
1.创建分支
#创建dev分支,并切换到dev分支
$ git checkout -b dev
# 查看当前分支
$ git branch
说明:
1.git checkout 命令加上 –b参数表示创建并切换,相当于如下2条命令
git branch dev //创建dev分支
git checkout dev //切换到dev分支
2.git branch 查看分支,会列出所有分支,当前分支会添加一个星号
eg:
创建dev分支,并在dev分支中添加README文件
#创建并切换分支到dev
$ git checkout -b dev
#查看当前分支
$ git bransh
#在dev分支添加README文件
$ touch README
#提交到本地工作区
$ git add README
#提交到本地仓库
$ git commit -m "dev分支添加README文件"
#将当前分支推送到远程仓库
$ git push https://github.com/jayfeihe/gittest1.git
2.切换分支
#切换到branch_name分支
$ git checkout branch_name
3.合并分支
git merge branch_name --- 合并指定分支内容到当前分支上
eg:
#将dev分支内容合并到master分支 --- 在master分支上执行下面命令!!!
$ git merge dev
4.删除分支
git branch -d branch_name
eg:
#合并完成后,就可以删除dev分支了
$git branch -d dev
5.分支操作命令总结:
查看分支:git branch
创建分支:git branch name
切换分支:git checkout name
创建+切换分支:git checkout –b name
合并某分支到当前分支:git merge name
删除分支:git branch –d name
6.冲突解决
eg:
分支fenzhi1中创建一个readme.txt并添加内容,
分支master中创建一个readme.txt并添加内容,
这时master合并fenzhi1时,会有冲突
$ git merge fenzhi1
Auto-merging jay/readme.txt
CONFLICT (add/add): Merge conflict in jay/readme.txt
Automatic merge failed; fix conflicts and then commit the result.
操作步骤:
1.创建fenzhi1,并新增readme.txt文件,然后提交到本地库
$ git checkout -b fenzhi1
#添加内容8888888
$ vi readme.txt
$ git add reame.txt
$ git commit -m "fenzhi1分支添加readme.txt文件"
2.切换到master分支,并新增readme.txt文件,然后提交到本地库
$ git checkout master
#添加内容11111111
$ vi readme.txt
$ git add reame.txt
$ git commit -m "master分支添加readme.txt文件"
3.master分支合并fenzhi1, 报冲突 conflict
$ git merge fenzhi1
Auto-merging jay/readme.txt
CONFLICT (add/add): Merge conflict in jay/readme.txt
Automatic merge failed; fix conflicts and then commit the result.
说明:
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,
<<<HEAD 指主分支修改的内容
>>>>>fenzhi1 指fenzhi1上修改的内容
eg:
$ cat readme.txt
<<<<<<< HEAD
11111111
=======
88888888
>>>>>>> fenzhi1
说明:
======= 之前的是HEAD分支内容,之后的是fenzhi1内容
4.解决冲突
修改冲突文件,然后提交
eg:
#将readme.txt文件内容改为 8888888,然后再提交即可
#1.解决冲突,修改文件内容
$ vi readme.txt
#2.添加冲突文件,并提高到本地库
$ git add readme.txt
$ git commit -m "conflict fixed"
$ git status
7.查看分支合并情况
git log
操作远程仓库的主分支和dev分支:
1.克隆远程分支
$ mkdir test
$ cd test
$ git clone https://github.com/jayfeihe/gittest1.git
2.查看当前分支
$ git branch
$ git branch -a 显示所有分支
3.切换到dev分支
$ git checkout dev
#如果无法切换,可先本地创建一个dev分支,然后通过git pull origin dev方式同步远程dev分支
4.修改内容,并提交到本地dev分支
$ touch dev-tag.txt //创建文件
$ git add . //添加文件到工作区
$ git commit -m "add file dev-tag.txt" //提交到本地仓库(dev分支)
5.提交修改到远程仓库dev分支
$ git remote
$ git push origin dev
6.合并dev到本地master
$ git checkout master
$ git merge dev
7.master提交到远程仓库
$ git push origin
8.master将dev-tag.txt修改为master-tag.txt,并提交到远程master分支
$ git checkout master
$ mv dev-tag.txt master-tag.txt
$ git status
$ git add .
$ git commit -m "remove dev-tag.txt ,add master-tag.txt"
$ git push origin
在弹出框中填写自己的github账号和密码
注意:添加和删除远程分支 --- 已经连接过github
1.添加远程仓库分支
$ git branch branch1
$ git checkout branch1
$ git branch
$ git push origin branch1
2.删除远程仓库分支
$ git push origin :branch1
3.克隆远程分支到本地
$ git checkout -b branch1 origin/branch1
8.分支管理策略
分支策略:
首先master主分支应该是非常稳定的,也就是用来发布新版本,一般情况下不允许在上面干活,干活一般情况下在新建的dev分支上干活,
干完后,比如上要发布,或者说dev分支代码稳定后可以合并到主分支master上来!!!
git 在合并分支时,默认使用 "Fast froward"模式,这种模式下,删除分支后,会丢掉分支信息,
可以使用参数 --no-ff 来禁止 "Fast froward"模式
eg:
创建一个dev分支。
修改readme.txt内容。
添加到暂存区。
切换回主分支(master)。
合并dev分支,使用命令 git merge –no-ff -m “注释” dev
查看历史记录
#dev分支上的操作
$ git checkout -b dev
$ git add readme1.txt
$ git commit -m "add merge"
#master分支上的操作
$ git checkout master
$ git merge --no-ff -m "merge with no-ff" dev
$ git branch -d dev
$ git log
说明:
1. 查看分支日志: 使用 --no-ff 参数,删除dev分之后,被删除的分支信息在log中仍然存在
2. 分支策略:
首先master主分支应该是非常稳定的,也就是用来发布新版本,一般情况下不允许在上面干活,干活一般情况下在新建的dev分支上干活,
干完后,比如上要发布,或者说dev分支代码稳定后可以合并到主分支master上来!!!
9.bug分支
Git中分支很强大,每个bug都可以通过一个临时分支来修复,修复完成后,合并该临时分支,然后删除临时分支即可
10.多人协作
当你从远程库克隆时候,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且远程库的默认名称是origin
1.查看远程库信息
git remote ---- 查看远程库信息
git remote -v ---- 查看远程库的详细信息
2.推送分支
推送分支就是把该分支上所有本地提交到远程库中,推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上
1.推送到master分支
git checkout master
git push origin master
2.推送到其他分支 dev
git push origin dev
特别注意:
那些分支需要推送?
1.master分支时主分支,要时刻与远程同步
2.一些修复bug分支,不需要推送到远程,可以先合并到主分支,然后把主分支master推送到远程去
3.抓取分支
git clone git远程库地址(HTTPS和SSH2种方式)
eg:
#新建或选择指定目录,执行命令
git clone https://github.com/jayfeihe/gittest1.git
eg:
#员工1 把dev分支推送到远程仓库
$ git checkout dev
$ git push origin dev
#员工2 新建testgit2目录,在该目录中,克隆远程仓库,切换到dev分支
$ mkdir testgit2
$ git clone https://github.com/jayfeihe/gittest1.git
#创建远程库origin/dev分支到本地dev分支,并切换到dev分支
$ git checkout -b dev origin/dev
#修改dev中的文件,并提交,然后把dev分支推送到远程库
$ vi readme.txt
xxxxx
$ git add readme.txt
$ git commit -m "readme.txt 增加xxxxx内容,推送给远程库dev分支"
#把3现在的dev分支推送到远程去
$ git push origin dev
注意:
1.如果推送到远程有冲突,解决方法:
git pull 把最新的提交从origin/dev抓下来,然后在本地合并,解决冲突,再推送
2.多人协作的一般模式:
首先,可以试图用git push origin branch-name推送自己的修改.
如果推送失败,则因为远程分支比你的本地更新早,需要先用git pull试图合并。
如果合并有冲突,则需要解决冲突,并在本地提交。再用git push origin branch-name推送。
冲突解决
1.多人协作冲突
如果多人同时修改了同一个文件,那会出现什么样的结果呢?我们试着这么做。
(1)修改jackygit2
在jackygit2中修改jackydata01,提交修改并推送到远程仓库(这里使用本地远程仓库)。正常,没问题。
- #切换到jackygit2本地库,这是远程仓库那节建立的,从本地远程仓库克隆而来
- $ cd ../jackygit2