Mac中Git版本管理

系统默认

Mac上装了xcode,会自带git,但一般版本比较旧。用命令which git,查看当前使用git安装的目录。 默认是安装在/usr/bin/git。

下载安装

从git-scm下载,安装最新版本的git,安装目录为/usr/local/git。

版本管理

使用命令open打开.bash_profile 文件,添加 export PATH=/usr/local/git/bin:${PATH},从而使得新版本到安装目录被优先搜索到。

MAC下Gradle安装路径

在Mac中使用brew安装gradle,则gradle目录为/usr/local/Cellar/gradle/2.12/libexec (其中2.12对应的是版本号)

在IntelliJ IDEA中使用本地的gradle时,需要安装上述目录去设置。

Git学习笔记 (6) - Branch基础

Git分支是轻量级的

在Git中,branch就是一个轻量级的file(40个字节),有一个特殊的指针HEAD来指示Git位于哪个分支。

和其他版本控制软件相比,Git分支是轻量级的,鼓励多用分支。

例如,在某个仓库下运行下来命令,可以看到这个仓库下有2个分支:master,testing,同时HEAD是指向master的,即当前工作的分支为master

1
2
3
$ git log --oneline --decorate
f30ab (HEAD -> master, testing)
...

分支常用命令

创建和switch

1
2
git branch testing     // 创建分支testing,但是仍在原先分支下
git checkout testing // Switch到分支testing

上述两条命令可以合并成一条命令:

1
git checkout -b testing

删除

和创建相比,多了一个option:-d

1
git branch -d testing

Merge 与 Rebase

例如,master分支合并testing分支

1
2
git checkout master     // 如果不在master分支下,需要先switch到master分支
git merge testing

把testing上改变rebase到master上面

1
2
git checkout testing
git rebase master

rebasemerge最后得到的新的snapshot是一样的,但是rebase可以得到a cleaner history(看上去history是一个串行的记录过程)。 而merge看到的history中间有分支然后再合流成一个(在merge的点)

list

把仓库里面的分支list出来:

1
git branch

分支管理其他命令

1
2
3
git branch -v           // 查看每个branch的最后一次commit
git branch --merged // 合并到当前分支的所有分支
git branch --no-merged // 未合并到当前分支的所有分支

Git学习笔记 (5) - Tag使用

标签Tag

Git中标签有两类:

  1. lightweight: just a pointer to a specific commit
  2. annotated

Annotated Tags

使用-a:

1
git tag -a v1.4 -m "My version 1.4"

Lightweight Tags

1
git tag v1.4

查看Tag

查看有哪些tag:

1
2
git tag
git tag -l "v1.8.5*" // 只显示以v1.8.5开头的标签

查看某个tag的信息:

1
git show v1.4

Push

Push命令不会自动把Tag信息包含,需要自己制定

1
2
git push origin v1.5
git push origin --tags // 所有的tags

Checkout

需要新建一个新的branch,然后指定tag:

1
2
git checkout -b [branchname] [tagname]
git checkout -b version2 v2.0.0

Git学习笔记 (4) - Git远程操作

克隆

1
git clone https://github.com/schacon/ticgit

仓库信息

1
2
git remote
git remote -v

如果需要查看远程仓库更详细的信息,可以使用:

1
git remote show [remote-name]

添加远程仓库和改名

添加

1
git remote add  <shortname>  <url>

移除

1
git remote rm remote-name

改名

1
git remote rename OldName NewName

获取远程仓库新数据

1
2
git fetch [remote-name]
git pull

两个差别是:fetch只获取新数据,而pull除了获取新数据,还会把新数据主动与当前工作的分支进行合并。

发布

1
2
git push [remote-name] [branch-name]
git push origin master

Git学习笔记 (3) - Git基本命令

创建Repository

有两种方式:

  1. 基于目录创建
  2. 克隆

基于目录创建

1
git init

上述命令创建了一个仓库,但是并没有把当前目录下面的文件都加入仓库,即还是一个空仓库,后续还需要 git add *.*, git commint -m 'xxxx'等命令

克隆

1
git clone url  [newName]

如果没有newName,则克隆的名字与原先仓库一样。

上述命令包含了几个操作:

  1. 从url地址下载仓库
  2. 在本地复制了下载的仓库
  3. 在当前目录checkout了一分工作文件(基于仓库中最新的版本)

文件状态和命令

在Git中,文件主要分为三种状态

  1. Modified: 文件修改了,还没进行任何其他操作(或者新文件,还没有被tracked)
  2. Staged:即下次commit会被记入的文件,相当于下次commit对应的indexing
  3. Committed:已经递交,所有变化已经被git所记录

Modified -> Staged

1
git add xx.xx

Staged -> committed

1
git commit -m 'coments and messages`

跳过Staged Area

使用git commit的同时添加参数-a,会自动把所有被tracked的文件的改动都自动stage,然后再递交:

1
2
git commit -a
git commit -a -m 'add xxxx'

查看文件状态

Git Status

可以详细列出处于各种状态的文件:

1
git status

上述信息如果嫌过多的话,可以使用short形式

1
2
git status --short
git status -s

输出分为两列

  • 第一列:文件状态(M:Modified, A:Staged(Added), ??: not traced)
  • 第二列:文件名称

Git Diff

显示staged以后做的修改的部分,如果staged以后,没有修改,则此命令没有输出。

1
git diff

如果需要看staged中的修改部分,即哪些修改后续将会进入commit,需要添加参数:

1
git diff --staged

忽略文件

项目当前目录下,修改文件.gitignore,一些规则如下:

  • #
    • 注释行
  • *
    • 0或更多个character
  • [abc]
    • a 或 b 或 c
    • 单个character
  • [0-9]
    • 0-9中间一个数
  • \
    • nested dirctories,例如a/**/z,匹配下面各种情况a/za/b/z, a/b/c/z
    • !lib.a,lib.a文件需要被tracked,不能ignore
  • /结尾
    • 表示目录,build/build目录下面所有文件
    • doc/**/*.pdfdoc目录下,所有的pdf文件

##查看Log

1
2
3
git log      // 最新的先显示
git log -p // 显示每次commit对应的difference
git log -2 // 显示最近2次的结果

其他文件操作

移除文件

从Git中移除,并且从working directory里面删除对应文件:

1
git rm xxx.yy

重命名文件

1
git mv name1 name2

上述命令等价于下面三个命令:

1
2
3
mv name1 name2
git rm name1
git add name2

重新递交

1
git commit --amend

把文件从staged状态移除

1
git reset HEAD xxxxxx

放弃修改

1
git checkout --xxxx.txt

Git学习笔记 (1) - 基本配置

配置的三个层级

Git使用 git config 来进行配置。按照控制范围来说,Git配置分为三层:

  1. 某个Repository
    1. 配置文件: .git/config
    2. 在当前的git repository目录下面使用命令: git config
  2. 当前用户
    1. 配置文件: ~/.gitconfig~/.config/git/config
    2. 使用命令: git config --global
  3. 所有用户
    1. 配置文件: /etc/gitconfig
    2. 使用命令: git config --system

上述三个层级,范围小的层级会override范围大的层级,即上面的配置可以override下面的配置。

配置参数

用户名

1
git config --global user.name "shizhihua"

邮箱

1
git config --global user.email xxxyyy@gmail.com

默认文本编辑器

如果不进行设置,Git会使用系统默认的文本编辑器。

1
2
git config --global core.editor emacs
git config --global core.editor "'C:/Programe Files/Notepad++/notepad++.exe' -multiInst -nosession"

在win下面,-multiInst -nosession需要,否则会出错。

查看配置

1
git config --list

上述命令会列出所有的配置。

如果需要列出某个key的配置值,可以利用下面的命令git config <key>

1
git config user.name

Git Aliases

通过设置,可以制定一些命令的简写方式,例如:

1
2
3
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.last 'log -1 HEAD'

则下面一些命令就可以简写如下:

1
2
git co       // git checkout
git last // git log -1 HEAD

Go中Map与Struct联合使用注意点

在Go中,如果map联合struct使用需要注意。

下面程序编译出错,因为 a[1].x =3无法编译通过,信息为:cannot assign to a[1].x

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
"fmt"
)

func main() {
type Test struct {
x int
y int
}

a := make(map[int]Test)

a[1] = Test{x: 1, y: 1}

a[2] = Test{x: 2, y: 2}

a[1].x = 3

fmt.Println(a[1], a[2])

}

如果map类型改为slice类型,则程序没有问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func main() {
type Test struct {
x int
y int
}

a := make([]Test,3)

a[1] = Test{x: 1, y: 1}

a[2] = Test{x: 2, y: 2}

a[1].x = 3

fmt.Println(a[1], a[2])

}

如果还要使用map类型,同时保持类似处理流程,则需要使用*struct,具体程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

func main() {
type Test struct {
x int
y int
}

a := make(map[int]*Test)

a[1] = &Test{x: 1, y: 1}

a[2] = &Test{x: 2, y: 2}

a[1].x = 3

fmt.Println(*a[1], *a[2])

}

Gradle生成可独立运行(runnable)程序

无法运行的jar文件

在Java程序中,经常需要使用第三方的库(一般以jar包的形式出现)。在脚本中,可以通过下面的方式添加依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apply plugin: 'java'

repositories {
mavenCentral()
}

dependencies {
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.5'
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.5'
}

jar {
manifest {
attributes 'Main-Class': 'com.shizhihua.example.TestLog'
}
}

按照上面生成jar文件,如果直接运行,会出现找不到依赖的问题。

生成runnable的jar文件

为了解决这个问题,可以在脚本中添加一段代码,生成胖jar文件。这样的jar文件可以直接运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apply plugin: 'java'

repositories {
mavenCentral()
}

dependencies {
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.5'
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.5'
}

jar {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }

manifest {
attributes 'Main-Class': 'com.shizhihua.example.TestLog'
}
}

application插件

1
2
3
4
5
6
7
8
9
10
11
12
apply plugin: 'application'

repositories {
mavenCentral()
}

dependencies {
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.5'
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.5'
}

mainClassName = "com.shizhihua.example.TestLog"

运行gradle tasks,可以看到很多的task。其中有两个常用的新task:

1
gradle run

可以直接运行程序,看到输出结果。

1
gradle installDist

可以生成可运行的文件(实际上是响应的脚本,指定了依赖库和运行的jar文文件),其中相关的依赖库也都被拷贝到对应的libs(build\install\testLog\libs)下面。可以通过下面的命令直接运行程序:

1
build/install/testLog/bin/testLog