git特点
直接记录快照,而并非差异比较
近乎所有操作都在本地执行
时刻保持数据完整性
多数操作仅添加数据
Git安装
Linux(Ubuntu)
Sudo apt-get install git
Windows
通过msysGit()
或者到https://git-scm.com/download/选择正确版本下载
Mac
安装命令行工具(如已安装Xcode,命令行工具会在首次启动Xcode时提示安装)
Homebrew
Macports
文件的三种状态
已修改(modified)
已暂存(staged)
已提交(commited)
git当中三个区域:工作区,暂存区,版本库
Git常用命令
创建版本库
直接使用git init命令
直接clone一个仓库:
$: git clone [email protected]:projects/search.git
另外一种clone方式:
# 创建目录初始化本地仓库
$: mkdir search && cd search
$: git init
分支操作
查看分支:git branch
创建分支:git branch name
切换分支:git checkout name
创建+切换分支:git checkout -b name
合并某分支到当前分支:git merge name
删除分支:git branch -d name
合并dev分支: git merge --no-ff -m "merge with no-ff" dev
上面我们使用的合并分支是fast forward(快进式合并),这种快速合并的模式,但是有个地方不好的就是不能显示历史信息,在以后开发中我不知道有哪些分支曾经合并过,所以最好使用 no-ff:no fast forward的合并方式,这种方式在合并的同时会生成一个新的commit,这样,从分支历史上就可以看出分支信息。
合并过程中,如果没有冲突的话,merge完成,有冲突的话,git会提示那个文件中有冲突。在解决了所有文件里的所有冲突后,运行 git add 将把它们标记为已解决(resolved)。因为一旦暂存,就表示冲突已经解决。如果你想用一个有图形界面的工具来解决这些问题,不妨运行 git mergetool,它会调用一个可视化的合并工具并引导你解决所有冲突。
Git merge --about 暂时不处理冲突,会清理暂存区
如果你不想把历史汇聚起来,但是想要一个具体分支中的全部commit,使用
Git merge --squash 目标分支名称 这会执行一次提交
删除文件和移动文件
git rm 文件名
删除单独的某个文件,并且它会暂存这个文件删除的事实。
Git add -u 目录名
会从当前目录递归到最深处,寻找它能够添加的所有文件,或者说所有能够被删除的文件(暂存区)
Git rm --cached file.txt
如果想删除一个文件,不想从文件系统中真正的删除它。告诉git不再跟踪这个文件,会有暂存。
在git中,重命名和移动文件是同一个事情
Git mv file1.txt file/file2.txt 将文件移动file文件下并命名为file2
当手工移动的时候,git会认为当前目录删除文件,另一个目录untracked了一个文件,使用命令git add -A 就可以合并这两次操作,并tracked文件。
Git commit -a/--all -m “comment”
git add -u,使用-u参数调用了git add命令,会将本地有改动(包括删除和修改)的已经追踪的文件标记到暂存区中。
git add -A/--all,使用-A参数会将添加所有改动的已跟踪文件和未跟踪文件。
移动文件,并tracked后,然后commit 会给我们一些数字,这个数字是相似度,表示文件在移动钱湖内容的相似度。Git默认提供一个50%的相似度阈值。如果文件在移动前后,50%相似,它会在移动的过程中追踪它,认为它是一个移动而不仅仅是一个删除和添加。我们可以改变这个阈值。
阈值(100%)
从其他分支提取文件:git checkout [branch] filename
远程仓库操作
# 添加远程仓库路径
$: git remote add github https://github.com/charmingfst/test.git
#如果发现url写错了,那么使用下面的命令修改
Git remote set-url github https://github.com/charmingfst/test.git
上传本地当前分支代码到master分支
$: git push github master
git push origin master (等价于“git push origin master:master”)
git push origin master:master (在local repository中找到名字为master的branch,使用它去更新remote repository下名字为master的branch,如果remote repository下不存在名字是master的branch,那么新建一个)
$git push origin HEAD:refs/for/mybranch (HEAD指向当前工作的branch,master不一定指向当前工作的branch,所以我觉得用HEAD还比master好些)
$git push origin :mybranch (再origin repository里面查找mybranch,删除它。用一个空的去更新它,就相当于删除了)
# 实际上,pull 就是 fetch + merge
$: git pull github --all --tags
git pull -rebase https://github.com/charmingfst/test.git //rebase绕过合并时的冲突
显示所有的远程仓库
$: git remote -v
origin [email protected]:projects/search.git (fetch)
origin [email protected]:projects/search.git (push)
github [email protected]:yyfrankyy/search.git (fetch)
github [email protected]:yyfrankyy/search.git (push)
重命名远程仓库
$: git remote rename github gh
$: git remote
origin
gh
删除远程仓库
$: git remote rm github
$: git remote
Origin
从远程仓库抓取数据,更新本地仓库:
$: git fetch origin
查看远程仓库信息,可用于跟踪别人的push:
$: git remote show origin
查看日志
Git log [filename] --oneline查看日志,每次提交信息在一行显示。
Git log sha1值 查看某个具体提交的信息
Git log -p 可以查看版本之间的代码差异。
Git log -n n用数字替代,可以查看最近n条日志记录。
Git log --stat 显示被修改文件的修改统计信息,添加或删除了多少行。
$ git log --since="5 hours" 表示显示5小时内的历史记录。
$ git log --before="5 hours" -1 表示显示5小时前的最后一条记录。
Git支持输出两个版本之间的日志记录。
$ git log 18f822e...0bb3dfb 表示输出在18f822e之后(不包括自己)到0bb3dfb之间(包括自己)的历史记录。
在表示版本的过程中可以使用HEAD表示当前的版本,如:
$ git log 18f822e...HEAD
也可以不输入HEAD,因为GIt假定"..."后面省略的值为HEAD,如:
$ git log 18f822e...
查明该向谁问责
可以使用命令git blame,查看特定代码块的历史信息。该命令的输出结果是代码块中的每行代码前附加前缀信息、其中包括提交名称、提交人和提交时间。
$ git blame file.txt
$ git blame -L 12,13 hello.html 将显示第12、13行代码的信息。
查看差异
显示工作目录树、暂存区及版本库之间的差异:
git diff:直接调用不带参数的git diff,将显示工作目录树中未被暂存(当然还没有提交)的改动。(比较的是工作目录树与暂存区)。
git diff --cached:添加参数--cached,是比较暂存区和版本库之间的区别。
git diff HEAD:添加参数HEAD,可以比较工作目录树(包括暂存的和未暂存的修改)与版本库之间的差别。HEAD关键字指的是当前所在分支末梢的最新提交(也就是版本库中该分支上的最新版本)。
git diff id1 id2,显示两次提交之间的差异
Gitk查看提交的历史记录
Git reset
有三种模式(mixed(默认),soft,hard)
git reset --hard <commit>,替换引用的指向,替换暂存区,替换工作区
git reset --soft <commit>,只更改引用的指向,不改变暂存区和工作区
Git reset --soft HEAD^(HEAD^表示当前节点的父节点)
当一些该动太过于分散,把他们弄到一起,比如5条commit,通过使用
Git reset --soft HEAD~5这个命令,把这5条commit当做一次提交。这对于重塑历史非常有用。
git reset HEAD用HEAD 重置暂存区,移除暂存区的变化。
git reset -- filename,将文件filename的改动撤出暂存区,暂存区其他文件不变
Reset与checkout的不同
Reset经常操作的是整个仓库的历史,checkout作用在一个目录或者文件级别上。
版本回朔
1、Git checkout sha1值(不用写全)
2、Git reset --hard <commit>
3、如果提交的文件中只有某个文件是想要的,其他文件丢弃改变 git checkout -- filename ,它会清理最后一次commit的内容。
避免暂存或提交文件
创建.gitignore文件,文件每行内容应与你需要的文件匹配
如 *.log(忽略所有log文件) temp/(忽略temp目录)
修改.gitignore文件后 运行Git add .gitignore,接下来提交的时候匹配的文件就会被忽略。
查看哪些文件被忽略了
Git ls-files --others --ignored --exclude-standard
显示出来的就是被忽略的文件
Reflog命令
Reflog命令会追踪所有的commit,这提供了一个30天的缓存时间,在这期间,你可以从任何错误中恢复,包括git reset命令带来的不好之处
通过git reset --hard hash串,目前的分支被强制切换到那个历史点。
Rebase命令
Rebase命令可以把已存在的提交,放到重新开始的一个分支上。
Rebase命令会修改所有提交在分支中的呈现,它保存你所有的工作。Rebase命令能够让你优化仓库历史的清晰度。
Git rebase master 将当前所在分支的提交放到master分支上。意味着,把所有仅在你分支的所有变更仿佛发生在主分支的当前工作之后
如果需要快速发表特色分支,那么使用merge合并
如果需要清晰的历史,那么使用rebase