Git安装
- 地址:https://git-scm.com/downloads
- 下载对应平台的git版本安装即可
Git配置
配置快捷命令
- 在用户根目录下(如C:/user/Administrator)新建配置文件命名为.gitconfig
- 将以下内容写入文件
[user]
email = xxx(邮箱如:foxleezh@gmail.com)
name = xxx(名字如:foxleezh)
[alias]
st = status
ci = commit
br = branch
co = checkout
glog = log --pretty=oneline
pus = push
pul = !git pull --rebase && git submodule update --init --recursive
lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
[merge]
tool = vim
[core]
packedGitLimit = 512m
packedGitWindowSize = 512m
[pack]
deltaCacheSize = 2047m
packSizeLimit = 2047m
windowMemory = 2047m
配置ssh
- 在命令行输入
ssh-keygen -t rsa
- 在用户目录(如C:/user/Administrator)打开.ssh文件夹,查看id_rsa.pub文件,将密钥拷贝到服务器密钥库
配置忽略文件
- 将.gitignore文件放置到项目根目录下
# OSX
*.DS_Store
# Gradle files
build/
build_out/
obj/
.gradle/
*/build/
captures/
gradle/
# IDEA
*.iml
.idea/.name
.idea/encodings.xml
.idea/inspectionProfiles/Project_Default.xml
.idea/inspectionProfiles/profiles_settings.xml
.idea/misc.xml
.idea/modules.xml
.idea/scopes/scope_settings.xml
.idea/vcs.xml
.idea/workspace.xml
.idea/libraries
.idea/runConfigurations.xml
.idea/compiler.xml
.idea/copyright/profiles_settings.xml
.idea/gradle.xml
.idea/
# Built application files
*.ap_
# Files for the Dalvik VM
*.dex
# Java class files
*.class
# Local configuration file (sdk path, etc)
local.properties
# Log Files
*.log
# Special
gradle.properties
- 凡是在列表中的文件(*表示所有)都将被git忽略,对这些文件的任何改动,git都不会追踪
- 但是有时我们只想追踪某几个文件,其它都忽略,可以如下配置,!后面的内容为追踪的文件
/*
!.gitignore
!README.md
Git使用
- 命令行使用(windows打开git bash , mac 打开终端)
- Git bash是命令行工具,内部使用linux指令集(linux使用文件另附)
- 更多linux命令http://www.php100.com/html/webkaifa/Linux/2009/1106/3485.html
一.准备工作
- 新建仓库(进入到项目的根目录下)
git init
- 添加忽略规则,将.gitignore文件放置到根目录下
- 添加文件,将需要管理的文件加入到根目录下
二.代码管理
- 查看状态
git st
红色表示已修改未保存到缓存区,绿色表示已保存到缓存区
Git有三个状态,一是修改未保存到缓存,二是保存到缓存,三是提交到版本库
我们可以对比着word文档来学习,状态一就相当于你在word中修改了一些东西,但是没有按ctrl+s键保存起来,状态二就是你修改了东西后按了ctrl+s,暂时存起来了,状态三就是点击了另存为,将它另外存放起来了
- 保存到缓存区
git add 文件路径(添加单个文件到缓存)
一开始修改了homepage和loading两个文件,git st后显示红色
使用git add后,将homepage加入到缓存区
git st后,发现homepage变为绿色
git add -u(添加所有修改到缓存)
一开始修改了homepage和loading两个文件,git st后显示红色
使用git add -u后,将homepage和loading一起加入到缓存区
git st后,发现homepage和loading变为绿色
git add . (添加所有文件到缓存,包括新建的文件)
此用法与git add -u类似,区别在于,git add -u只能将修改的文件加入缓存,如果该文件是新建的,要使用git add ., 这个“.”符号表示所有
- 撤销缓存区的文件
git reset 文件路径(撤销单个文件)
首先git st后发现,有两个已经加入到缓存区的homepage和loading文件
使用git reset homepage后,将homepage文件撤销
git st后发现,homepage变为红色
git reset(撤销所有缓存区的文件)
首先git st后发现,有两个已经加入到缓存区的homepage和loading文件
使用git reset后,将所有文件撤销
git st后发现,homepage和loading都变为红色
- 撤销修改
git co 文件路径(撤销单个文件的修改)
首先使用git st,发现有homepage和loading两个文件被修改
使用git co homepage,撤销homepage的修改
git st后发现homepage文件不见了,查看原代码,代码中的修改也没有了
git reset --hard (撤销所有文件的修改)
首先使用git st,发现有homepage和loading两个文件被修改
使用git reset --hard,撤销所有的修改
git st后发现homepage和loading文件不见了,显示nothing to commit,working directory clean, 这表示当前没有任何的修改
- 查看修改的内容
git diff 文件路径(查看单个文件修改)
首先使用git st,有两个文件Homepage,loading被修改
使用git diff homepage,可以看到哪些被修改了,按箭头上下可以翻动,”-”号表示删除(红色显示),”+”号表示添加(红色显示)
查看完成后输入q,即可退出查看
要查看所有修改直接用git diff
git diff --cached (查看处于缓存区的修改)
首先使用git st,有两个文件Homepage,loading被加入到缓存区
使用git diff homepage,可以看到哪些被修改了,按箭头上下可以翻动,”-”号表示删除(红色显示),”+”号表示添加(红色显示)
查看完成后输入q,即可退出查看
要查看所有修改直接用git diff --cached
- 将缓存区的内容提交到版本库
git ci -m “我修改了什么”
首先git st,发现有两个文件homepage和loading加入到缓存区
使用git ci -m “注释”,将缓存区的内容提交到版本库,这里注释是随便写的,用于提示该commit修改了一些什么内容
git st后发现,缓存区中的内容不见了,这是因为已经提交到版本库中了
- 查看版本库中的内容
git log
git log后发现有两个提交,“我修改了什么”是刚刚提交的commit,下面来分析下:
commit ac76744b1843665d0c6cf1add7cf758bc824c89a (这行是一个md5值,用来唯一标识commit的)
Author: foxleezh foxleezh@gmail.com (这行是说明该commit是谁提交的)
Date: Fri Jul 10 10:02:16 2015 +0800 (提交的时间)
我修改了什么 (之前我们写的注释)
- 查看某个提交中修改的内容
git show commit号
git show ac76744b, 这个ac76744b就是之前git log时对应的md5值,可以只取前6位
查看完成用q退出
我们回顾一下已讲的内容,一般来说使用流程都是
- 修改了一些内容,用git st看看状态
- git diff看看修改了哪些内容
- 确认无误后,将需要提交的内容git add加入到缓存区
- git ci -m 加入到版本库中,这里说一下,平常我们都用git ci -m新建一个commit,其实通常我们不用新建commit,而是用git ci --amend追加的方式
这里我们修改了loading中的内容,然后git add -u 加入到缓存区,因为我们只是修改了很少的内容,不需要重新提交commit,所以使用git ci --amend追加到之前的commit,这时会让我们修改注释内容
这是一个vim的编辑器,之前linux中有讲,按i进入编辑模式,箭头移动光标就可以修改注释,修改好后,按ESC进入一般模式,按:进入命令模式,输入wq,保存退出
git log后发现没有新建commit,只是追加到了之前的commit
我们在使用的过程中可能要回到某一个提交,这时可以使用git reset命令,这个命令可以带参数,--mixed(回到修改未保存状态),--soft(回到缓存区状态),--hard(删除所有修改),默认是--mixed
先讲讲--hard,这个好理解,就是把这个commit之后的所有修改都删除
这里有四个commit
我们先使用git reset --hard ,将“我修改了名字”之后的所有修改的删除
git st后发现,没有任何修改
git log后,已经回到”我修改了名字”的commit
下面我们试试git reset --mixed或者git reset
git log我们会发现--mixed和--hard都回到了“我修改了名字”的版本,区别在于git st后--mixed将“测试reset1”和“测试reset2”中修改的内容保留下来了,这样好处在于,我们有时回到某一个commit不是要删除所有的修改,而是只想改变某一些东西,这时我们把需要改的地方改掉后,再重新提交一个commit,这样会方便很多
最后我们试试git reset --soft
这个跟git reset --mixed差不多,只是它是把之后的修改放入了缓存区
三.分支操作
之前我们的操作都是同一个分支上的操作,现在我们引入分支的概念
- 查看分支
git br
git默认都会有一个分支叫master,这个分支叫主分支,一般来说我们提交代码的时候是用这个分支来提交,但是实质上它跟普通的分支没有什么区别
为什么我们要引入分支,svn也有分支的概念,但是基本是在服务器端,我们本地基本是在一个分支上修改内容的,然后commit,有时我们改一个东西A可能需要很长时间,当还没有改完却突然要修改另外一个东西B,而且A因为没有改完不能合并到版本库,这时svn就有点乏力了,我们可能要把之前没改完的东西A删除掉,然后再来改接下来的B。
git因为是分布式的,不管是服务器端还是本地,都可以存在很多分支,这样就方便我们利用分支很好地管理代码,当我们修改任务A的时候,我们可以在分支A上修改,分支A在master的基础上新建而来,当我们还没有处理完A就要处理B时,我们可以新建另一个分支B,也是在master的基础上新建而来,这样当我们处理完B,提交后,可以回到A,继续我们之前的开发,当我们开发完A,要提交的时候,我们把B的内容整合进来,这个涉及到分支合并,我们之后再讲
- 新建分支
git co -b TEST //新建名为TEST的分支,当前的分支会以绿色显示
当我们新建分支时,是从当前分支的基础上新建的,新建的分支保留了当前分支所有的修改,所以新建分支相当于对当前分支的一份拷贝,而不是一个空的分支
- 切换分支
git co master //切换到master分支
- 删除分支
git br -D TEST //D大写,表示强制删除
-
分支合并
讲合并,我们就回到之前那个例子,我们处理A任务和B任务都新建一个分支分别为TESTA和TESTB,这两个分支都是在master的基础上新建过来的
这里有三个分支,分别是master,TESTA,TESTB
主分支master有两个提交
git co TESTA切换到TESTA,上面有三个提交,在master基础上多了一个“测试A”的提交
git co TESTB切换到TESTB,上面有三个提交,在master基础上多了一个“修改B”的提交
现在我们需要把A和B合并到一起
首先切换到TESTA分支,然后使用git rebase TESTB命令,将TESTB合并到TESTA前面
一般来说,如果两个分支没有冲突的话,合并就完成了,像上图有冲突就需要解决冲突
git st后发现,TESTA和TESTB都修改了loading文件
git diff loading后,查看具体的冲突内容,git用特殊的符号标记冲突,<<<<<< HEAD到=======之前是你要合并的分支对当前文件的修改,因为现在我是要把TESTB合并到TESTA,所以HEAD就代表TESTB的修改,也就是“我是用来追加的B”是TESTB的修改,然后======与>>>>>>之前的内容是TESTA的修改,也就是“我是用来追加的A”这句话
现在我们要做的就是确认好是保留A的内容,还是保留B的内容,还是A和B的内容都保留,我们修改可以用linux的vim工具来修改,也可以直接在Android studio或者xcode中修改,修改时先将<<<<<,======这些特殊标记符号去掉,然后再进行修改
修改完成后,git add -u 将修改的内容加入到缓存区
然后git rebase --continue,继续rebase操作
如果要放弃合并,使用git rebase --abort
合并完成后git log,我们可以看到,TESTB的修改“修改B”已经合并进TESTA了,这时TESTA分支中就包含了A和B的修改
四.与远程服务器交互
- 生成rsa密钥
ssh-keygen -t rsa
查看id_rsa.pub文件,将密钥拷贝到服务器密钥库
- 从远程复制仓库
git clone 服务器仓库地址
一般来说是新建一个空目录,然后去克隆服务器的git仓库
- 在服务器添加仓库
1.新建本地仓库
git init
2.添加远程仓库地址
git remote add origin ssh://****@****:29418/foxleezh/test.git
3.提交远程仓库
git push origin master
4.切换到远程分支
git br -r 查看远程分支
git co 切换到某一个远程分支
5.删除远程分支
git push origin :branch
6.拉取服务器分支并切换到临时分支
git fetch origin branchname && git co FETCH_HEAD
如:
git fetch origin GIT && git co FETCH_HEAD
7.拉取服务器分支并合并到master
git pull
pull命令相当于fetch命令加上merge命令,将服务器master分支的内容拉下来并合并到本地master
git pull --rebase
以rebase形式拉取,相当于fetch命令加上rebase命令
如果是pull其他分支,加上分支名
git pull origin branchA
8.向服务器提交分支
git push
如果是push其他分支,加上分支名
git pull origin branchA
9.常见错误
- unable to rewind rpc post data - try increasing http.postBuffer
git config http.postBuffer 524288000
- 高版本不支持ssl
Host www.xxx.com(改成服务器地址)
HostkeyAlgorithms ssh-dss
五.子模组
- 新建子模组
1.新建父项目、子项目并上传服务器
2.克隆父项目、子项目到不同目录
git clone ssh://<username>@<hostname>:29418/project-1.git
git clone ssh://<username>@<hostname>:29418/lib1.git
git clone ssh://<username>@<hostname>:29418/lib2.git
3.将子项目变为父项目的子模组
git submodule add ssh://<username>@<hostname>:29418/lib1.git libs/lib1(这里目录可以自由更改)
git submodule add ssh://<username>@<hostname>:29418/lib2.git libs/lib2
4.将父项目修改的修改提交服务器
git add -u
git push
至此,子模组新建完成
- 修改子模组
1.进入子模组目录提交并上传
git add -u
git push
2.进入父项目提交并上传
git add -u
git push
- 克隆子模组
1.克隆父项目
git clone --recursive ssh://<username>@<hostname>:29418/project-1.git
2.切换子项目分支
到子目录下(此时分支处于游离状态)
git co -b newBranch
- 更新子模组
1.在父目录下更新
git pull
git submodule update
2.切换子项目分支
此时分支处于游离状态
git co -b newBranch
- 删除子模块(分4步走)
1.根据路径删除子模块的记录
$ git rm --cached [path]
2.编辑“.gitmodules”文件,将子模块的相关配置节点删除掉
清理子模块配置
3.编辑“ .git/config”文件,将子模块的相关配置节点删除掉
清理子模块配置
4.手动删除子模块残留的目录
清理脏文件
六、其他
- Git找回commit
git reflog
-
开发流程(以master为例)
- 在master的基础上新建一个分支进行修改
git co -b newbranch
- 在新的newbranch上改好代码后commit
git add -u
git ci -m "newbranch的修改"
- 切换到master上拉取最新代码,防止别人上传了代码自己却没有更新
git co master
git pull origin master
- 如果服务器有代码更新,切换回newbranch合并服务器新增代码(如果没有更新,直接执行第5步)
git co newbranch
git rebase master
- 切换到master,合并newbranch代码
git co master
git rebase newbranch
- 提交代码到服务器
git push origin master
- 在master的基础上新建一个分支进行修改
-
有关git rebase的常识
- 对于rebase的顺序
比如 上例中newbranch和master两个分支的合并
一开始两分支commit都是1,2,3
后来newbranch提交了一个4,commit就是1,2,3,4的顺序
而master拉取服务器更新了5,commit就是1,2,3,5的顺序
这时我们切换到newbranch,去rebase master,即git rebase master
rebase后的顺序是1,2,3,5,4
如果我们当初是切换到master,去rebase newbranch
rebase后的顺序是1,2,3,4,5
这里的法则就是,去rebase哪个分支,就把哪个分支塞在下面
- 对于rebase冲突的解决
当我们rebase后,看见有冲突,git st后可以看到冲突的文件
我们通过Android studio找到冲突的文件,去搜索=====或者<<<<<<这些特殊标记就会找到冲突的代码
修改冲突的代码为你想要的代码后,记得将=====,<<<<<这些特殊符号去掉
修改好后git add -u,将修改的代码提交到缓冲区
git rebase --continue继续rebase,这样就将冲突解决了
如果rebase过程中想取消,git rebase --abort
- 能过rebase删除某几个commit
比如newbranch上的commit为1,2,3,4
这时我想将中间的2和3去掉,变为1,4
我们首先要将2和3的commit号记下,比如是commit2,commit3
然后git rebase --onto commit2空格commit3(commit2后面的是前一个的意思,这个符号在键盘的数字6上面)
其实可以是git rebase --onto commit1空格commit3(因为commit2^就是commit1)
- 对于rebase的顺序
-
一些Linux常用命令
tab 补全命令
ctrl+c 停止执行
- 文件管理
pwd 打印当前目录
cd 进入某个目录
cd /home/develop 进入绝对路径
cd eclipse 进入相对路径
cd ../ 返回上一级目录touch [file name]打开或创建一个文件
mkdir -p [dir name] 创建一个目录 -p为强制创建
rm -r [file name/dir name] 删除一个文件或目录
ls -al 列出所有文件(包括隐藏文件)的详细信息
-d 只列出该目录的信息cp -rd [目标文件] [目的文件] 复制文件
-r是允许目录cp
-d是在拷贝软连接时只拷贝软连接,如果不加则会把原文件一起拷过去
cp -rd test.txt dir/test.txtmv -i [目标文件] [目的文件] 移动文件
-i是询问是否覆盖同名文件,如果[目标文件][目的文件]相同,那就是重命名find [dn] [参数]
如:find $HOME -name 'foxlee' -o -type f -o -size +20M
-atime +n :访问或执行时间大于n天的文件
-ctime +n :写入、更改inode属性(例如更改所有者、权限或者连接)时间大于n天的文件
-mtime +n :写入时间大于n天的文件
文件的 Access time,atime 是在读取文件或者执行文件时更改的。
文件的 Modified time,mtime 是在写入文件时随文件内容的更改而更改的。
文件的 Create time,ctime 是在写入文件、更改所有者、权限或链接设置时随 Inode 的内容更改而更改的。
因此,更改文件的内容即会更改 mtime 和 ctime,
但是文件的 ctime 可能会在 mtime
未发生任何变化时更改,例如,更改了文件的权限,但是文件内容没有变化。
这里讲一下ls中显示的时间
ls -lc filename 列出文件的 ctime
ls -lu filename 列出文件的 atime
ls -l filename 列出文件的 mtime
继续讲find的参数
-name 'filename' 直接查找该文件名的文件(注意加引号)
-type type :通过文件类型查找 type 包含了 f, b, c, d, l, s 等等
d 表示该文件为目录;
f 表示该文件为普通文件;
b 表示该文件为块设备文件,比如磁盘分区
l 表示该文件为连接文件(linux file),上边提到的软连接即为该类型;
c 表示该文件为串行端口设备,例如键盘、鼠标。
s 表示该文件为套接字文件(socket),用于进程间通信。
- 文件查看与编辑
vim [fn] 编辑文件 有三种模式(一般模式,编辑模式,命令模式),可以自由切换
一般模式下移动光标(esc回到一般模式)
箭头上下左右一般模式下查找与替换
/word 向光标之后寻找一个字符串名为word的字符串,当找到第一个word后,按”n”继续搜后一个,"N"前一个一般模式下删除、复制粘贴
dd 删除光标所在的那一行
yy 复制光标所在的那行
p,P p复制的数据从光标下一行粘贴,P则从光标上一行粘贴
u 还原过去的操作进入编辑模式(按i进入)
i 在当前字符前插入字符命令模式(按:进入)
:q! 不管编辑或未编辑都不保存退出
:wq 保存,退出
:e! 将文档还原成最原始状态
:set nu 在每行的行首显示行号
:set nonu 取消行号
- 文件管理