安装时密钥生成步骤
注意参数大小写,并且不用设置密码(直接回车)git config --global user.name "xxx" git config --global user.email "xxx@xxx" ssh-keygen -t rsa -C "xxx@xxx"
git hash 命令窗口相关设置
鼠标点击git hash 界面的标题栏,鼠标右键选择
A. 串口尺寸设置
options --> windows -->修改行数(高度)+列数(宽度)
B. 窗口字体设置
options --> text -->设置字体大小
C. git在Windows下的中文乱码问题
在Linux及托管网站上默认的编码都是utf-8,而Windows系统默认编码不是采用utf-8,所以需要进行某些设置
在命令行输入以下命令:
1
2
3
4
5
6
| $ git config --global core.quotepath false # 显示 status 编码
$ git config --global gui.encoding utf-8 # 图形界面编码
$ git config --global i18n.commit.encoding utf-8 # 提交信息编码
$ git config --global i18n.logoutputencoding utf-8 # 输出 log 编码
$ export LESSCHARSET=utf-8
# 最后一条命令是因为 git log 默认使用 less 分页,所以需要 bash 对 less 命令进行 utf-8 编码
|
以上命令等效于:
在etc\gitconfig中添加
1
2
3
4
5
6
7
| [core]
quotepath = false
[gui]
encoding = utf-8
[i18n]
commitencoding = utf-8
logoutputencoding = utf-8
|
在etc\profile中添加
1
| export LESSCHARSET=utf-8
|
说明:
a. gui.encoding = utf-8解决了$ git gui和gitk里中文乱码。如果发现代码中的注释显示乱码,可以设置项目根目录中.git/config文件添加
1.[core]
2. quotepath = false
b. il8n.commitencoding = utf-8设置commit log提交时使用utf-8编码,可避免服务器乱码,同时与Unix上的提交保持一致!
c. il8n.logoutputencoding = gbk 使得在$ git log时编码设置为utf-8
d. export LESSCHARSET=utf-8使得$ git log可以正常显示中文(配合il8n.logoutoutputencoding的设置)
ls 命令可以显示中文名称
修改etc\git-completion.bash文件
1
| alias ls="ls --show-control-chars --color" |
创建本地仓库
//从零开始创建
1.git init 创建一个空的Git库。在当前目录中产生一个.git 的子目录。以后,所有的文件变化信息都会保存到这个目录下
2.git init --bare 创建备份仓库(在服务器或者工程目录以外路径都可以创建的备份仓库)
// 克隆已有仓库创建
git clone /path/to/repository // 本地库
git clone git/ssh/http[s]/ftp[s]/file/rsync:username@ip/path/to/repository // 远端服务器
git clone的本质就是把“Git目录”里面的内容拷贝过来,一般的“Git目录”里有成千上万的各种对象(提交对象,树对象,二进制对象, tag对象......),如果逐一复制的话,其效率就可想而知。
如果通过git、ssh协议传输,服务器端会在传输前把需要传输的各种对象先打好包再进行传输;而http(s)协议则会反复请求要传输的不同对象。如果仓库里面的提交不多的话,前者和后者的效率相差不多;但是若仓库里有很多提交的话,git、ssh协议进行传输则会更有效率。不过现在Git对http(s)协议传输Git仓库做了一定的优化,http(s)传输现在也能达到ssh协议的效率
COMMIT_EDITMSG # 保存着上一次提交时的注释信息
config # 项目的配置信息
description # 项目的描述信息
HEAD # 项目当前在哪个分支的信息
index # 索引文件,git add之后要添加的内容暂存在这里
hooks/ # 默认的“hooks” 脚本文件
info/ # 里面有一个exclude文件,指定本项目要忽略的文件 #,看一下这里
logs/ # 各个refs的历史信息
objects/ # 这个目录非常重要,里面存储都是Git的数据对象
# 包括:提交(commits), 树对象(trees),二进制对象 #(blobs),标签对象(tags)。
# 在objects目录下,SHA串的前两个字符作为目录名,后面的38个字符作为文件名
refs/ # 标识着你的每个分支指向哪个提交(commit)。
// 查看提交文件的内容,2d832d是SHA(安全hash算法)签名值
$ git cat-file -p 2d832d
工作流
本地和远程工作流
你的本地代码 由 git 维护的三棵“树”组成。第一个是你的 工作目录
,它持有实际文件;第二个是 缓存区
(Index/stage)
,它像个缓存区域,临时保存你的改动;最后是本地仓库( HEAD)
,指向你最近一次提交后的结果
git clone 用于建立本地仓库 // origin 是git clone默认使用的远程主机名
通过git clone获取远端git库后,.git/config中的开发者信息不会被一起clone过来。仍然需要为本地库的.git/config文件添加开发者信息。此外,开发者还需要自己添加 . gitignore文件。
通过git clone获取的远端git库,只包含了远端git库的当前工作分支。如果想获取其它分支信息,需要使用 “git branch –r” 来查看, 如果需要将远程的其它分支代码也获取过来,可以使用命令 “ git checkout -b 本地分支名 远程分支名”,
其中,远程分支名为 “git branch –r” 所列出的分支名, 一般是诸如“origin/分支名”的样子。如果本地分支名已经存在, 则不需要“-b”参数。
git fetch
从远程获取最新版本到本地,不会自动merge,比git pull更安全些。
如果先使用 git fetch ,再使用git checkout nov/eclair_rocket,则是先从服务器上获取最新的更新信息,然后从服务器上下载最新的代码。
git pull
从服务器的仓库中获取代码,和本地代码合并。等同于: Git fetch + Git merge
这条命令将从远端git库的远端分支名获取到本地git库的一个本地分支中。其中,如果不写本地分支名,则默认pull到本地当前分支。 如果你的本地分支已经有内容,则git pull会合并这些文件,如果有冲突会报警。
git pull
和git push
是针对所有分支进行的操作。也就是说即使我切换到一个次分支alpha
, 如果这个分支和远端的分支已关联了的话,那么执行git pull
会把master
分支和alpha
分支都更新到远端。
添加和提交
添加命令指示添加到缓存区,使用如下:
git add dir1 # 添加dir1这个目录,目录下的所有文件都被加入
git add f1 f2 # 添加f1,f2文件
git add . #将本地所有的(新增和修改,没有删除)文件添加到暂存区
git add -u #将本地的(修改和删除,没有新增)文件添加到暂存区
git add -A/* #添加当前目录下的所有文件
#git add -A = git add . + git add -u
git add . #添加当前目录下的所有文件和子目录
git rm --cache a.c #删除已提交到本地仓库的文件
这是git基本工作流程的第一步;使用如下命令以实际提交改动
git commit -m "代码提交信息"
git commit -a -m "代码提交信息" # git commit -a是把unstaged的文件变成staged(这里不包括新建(untracked)的文件),然后commit
git commit --amend # 修改提交的commit(没有push)
git commit --amend -m "comment" # 修改commit注解
现在,改动已经提交到了HEAD,但是还没到远程仓库。
推送改动
当改动已经在HEAD中了,执行如下命令以将这些改动提交到远程仓库:
git push不会自动合并文件。因此,如果git push时,发生了冲突,就会被后push的文件内容强行覆盖,而且没有什么提示。 这在合作开发时是很危险的事情。<span style="font-family: 'Courier New'; white-space: pre-wrap;"> </span>git push origin master
可以把master换成你想要推送的任何分支。
如果你还没有克隆现有仓库,并欲将你的仓库连接到某个远程服务器,你可以使用如下命令添加:git remote add origin <server>
如此你就能够将你的改动推送到所添加的服务器上去了
分支
分支是用来将特性开发绝缘开来的。在你创建仓库的时候,master 是“默认的”。在其他分支上进行开发,完成后再将它们合并到主分支上。
git checkout -b feature_x //创建一个叫做“feature_x”的分支,并切换过去
切换回主分支:
git checkout master
再把新建的分支删掉:
git branch -d feature_x
除非你将分支推送到远端仓库,不然该分支就是 不为他人所见的:
git push origin <branch>
重命名本地分支
git branch -m branch-old-name branch-new-name
更新
要更新你的本地仓库至最新改动,执行:
git pull origin <remote-branch> <local-branch> git fetch origin <remote-branch>
标签
在软件发布时创建标签,是被推荐的。这是个旧有概念,在 SVN 中也有。可以执行如下命令以创建一个叫做 1.0.0 的标签:
git tag 1.0.0 1b2e1d63ff
1b2e1d63ff 是你想要标记的提交 ID 的前 10 位字符。使用如下命令获取提交 ID:
git log
你也可以用该提交 ID 的少一些的前几位,只要它是唯一的。
//给tag添加注释
git tag -v1.4 -m 'my version 1.4'
// 显示tag版本记录 git show tag-name // 一次性推送所有tag到远程服务器 git push origin --tags
// 取出打过tag的某个版本 git checkout -b branch_name tag_name
// 删除tag时需注意,如果向远程服务器提交了tag,则删除tag时,不仅要删除本地的tag,还要删除远程的tag // 删除本地的tag命令是 git tag -d tag-name // 删除远程tag的命令是 git push origin --delete tag-name
替换本地改动
假如你做错事(自然,这是不可能的),你可以使用如下命令替换掉本地改动:
git checkout -- <filename>
此命令会使用 HEAD 中的最新内容替换掉你的工作目录中的文件。已添加到缓存区的改动,以及新文件,都不受影响。
假如你想要丢弃你所有的本地改动与提交,可以到服务器上获取最新的版本并将你本地主分支指向到它:
git fetch origin master git reset origin/master --hard
git忽略文件的设置方式
可参考以下两个网址
git ignore文件的三种设置方式[http://www.jianshu.com/p/267cd94f1d49 ]
git ignore文件设置的具体语法[http://www.cnblogs.com/pylemon/archive/2012/07/16/2593112.html#3226325]
重点说一下踩过的坑:
.gitignore 文件可以忽略自己。忽略的文件,只针对未跟踪文件有效,对已加入版本库的文件无效。
git check-ignore 可用来检查所写的忽略文件语法是否正确
忽略文件的原则是:
1.忽略操作系统自动生成的文件,比如缩略图等;
2.忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的
.class
文件;3.忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。
不需要从头写
.gitignore
文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了,比如分别输入Tags和SublimeText,在下面的网址中查询忽略规则 https://www.gitignore.io/git分支合并
假设此时,你突然接到一个电话说有个很严重的问题需要紧急修补,那么可以按照下面的方式处理:
- 返回到原先已经发布到生产服务器上的分支。
- 为这次紧急修补建立一个新分支,并在其中修复问题。
- 通过测试后,回到生产服务器所在的分支,将修补分支合并进来,然后再推送到生产服务器上。
- 切换到之前实现新需求的分支,继续工作。
$ git checkout -b iss53 // 在master分支上新建一个iss53分支
相当于执行下面这两条命令:
$ git branch iss53 $ git checkout iss53
// 将hotfix分支合并到master $ git checkout master $ git merge hotfix
合并时发生冲突的提示信息
$ git merge iss53 Auto-merging index.html CONFLICT (content): Merge conflict in index.html Automatic merge failed; fix conflicts and then commit the result.
合并状态的查看
任何包含未解决冲突的文件都会以未合并(unmerged)的状态列出。Git 会在有冲突的文件里加入标准的冲突解决标记,可以通过它们来手工定位并解决这些冲突。可以看到此文件包含类似下面这样的部分:
可以看到
=======
隔开的上半部分,是HEAD
(即master
分支,在运行merge
命令时所切换到的分支)中的内容,下半部分是在iss53
分支中的内容。解决冲突的办法无非是二者选其一或者由你亲自整合到一起。比如你可以通过把这段内容替换为下面这样来解决:这个解决方案各采纳了两个分支中的一部分内容,而且我还删除了
<<<<<<<
,=======
和>>>>>>>
这些行。在解决了所有文件里的所有冲突后,运行git add
将把它们标记为已解决状态(译注:实际上就是来一次快照保存到暂存区域。)。因为一旦暂存,就表示冲突已经解决。
git branch -d studyGit // 对studyGit分支进行合并后,才能删除得了studyGit分支 git branch -D studyGit // 强制删除studyGit分支
再运行一次
git status
来确认所有冲突都已解决:$ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: index.html
如果觉得满意了,并且确认所有冲突都已解决,也就是进入了暂存区,就可以用
git commit
来完成这次合并提交。提交的记录差不多是这样:
git merge和git rebase合并分支的差异
git rebase生成的历史记录线比较好看
开发过程中,若你在开发的branch功能比较多, commit的量也比较多时,建议使用rebase将你现在的branch整理过再合并回主干,这样会产生较漂亮的线
git 版本回滚
Git的版本回退速度非常快,因为Git在内部有个指向当前版本的
HEAD
指针,当你回退版本的时候,Git仅仅是把HEAD从指向append GPL
版本号没必要写全,前几位就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。
git reset --hard 3628164
git rever 和git reset的区别
git revert 和 git reset 只有在回退最近的一次提交时,才是等效的
(1)git revert会使提交记录增多,git reset会使提交记录减少
(2)git revert只是撤销指定版本的提交,git reset是回卷,会撤销指定版本之后的所有提交
git reset HEAD~3
git revert HEAD~3
(3) git reset只能针对本地操作,不能对远程服务器执行同样的操作。
git rever和git reset的后悔药
revert后如果不想撤销了,看一下log,reset回去就可以了。
reset后后悔了怎么办,没有log了!没关系,下面命令可以查到更多commit ID:
git reflog
再输入:
git reset <commit ID>这个commit ID是上次reset前的ID,就可以回退会reset以前状态了。
在Git中,总是有后悔药可以吃的
git reflog 记录你操作的每一条指令
HEAD
指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
。穿梭前,用
git log
可以查看提交历史,以便确定要回退到哪个版本。要重返未来,用
git reflog
查看命令历史,以便确定要回到未来的哪个版本。
有用的贴士
内建的图形化 git:gitk
彩色的 git 输出:git config color.ui true
显示历史记录时,只显示一行注释信息:git config format.pretty oneline
如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline
参数:
git log --pretty=oneline
你看到的一大串类似3628164...882e1e0
的是commit id
(版本号),和SVN不一样,Git的commit id
不是1,2,3……递增的数字,而是一个SHA1计算出来的一个非常大的数字,用十六进制表示,而且你看到的commit id
和我的肯定不一样,以你自己的为准。为什么commit id
需要用这么一大串数字表示呢?因为Git是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就冲突了。
在Git中,用HEAD
表示当前版本,也就是最新的提交3628164...882e1e0
(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
。
想进一步了解git指令的话,可阅读下面几篇文章