Git使用,实战版

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使用

一.准备工作

  • 新建仓库(进入到项目的根目录下)
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
  • 有关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)
  • 一些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.txt

      • mv -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 取消行号

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • git常用命令 GIT常用命令备忘:http://stormzhang.com/git/2014/01/27/gi...
    新篇章阅读 8,458评论 1 26
  • 对于运营人员来说,现在的工作越分越细。在经过行业大牛和运营高手们的不断完善和总结后,如今的运营工作笼统的可分为三大...
    诸葛io阅读 4,914评论 1 11
  • 搞错了,身体需要原料 人体的修复能力是不是非常的神奇?可以说是无所不能,人体内的一切损伤都能通过修复而治愈,而且速...
    璀璨星空888阅读 613评论 0 1
  • 不信任自己的人,连努力的价值都没有。
    起风了雯雯阅读 183评论 0 0