Fork me on GitHub

随笔分类 - git

git命令总结

# 1.常用操作 [TOC] ## 1.1 新建代码库 ``` # 在当前目录新建一个Git代码库 git init # 新建一个目录,将其初始化为Git代码库 git init [project-name] # 下载一个项目和它的整个代码历史 git clone [url] ``` ## 1.2 配置 ``` # 显示当前的Git配置 git config --list # 编辑Git配置文件 git config -e [--global] # 设置提交代码时的用户信息 git config [--global] user.name "[name]" git config [--global] user.email "[email address]" ``` ## 1.3 remote管理 ``` # 远程主机名(git要求每个远程主机都必须指定一个主机名,克隆的时候会被自动命名为origin) git remote # 如果clone时候想用其它主机名,则加-o选项 git clone -o jQuery https://github.com/jquery/jquery.git # 查看远程主机网址 git remote -v # 查看主机详细信息 git remote show origin # 添加远程主机 git remote add origin https:git.xxxx.git # 删除远程主机 git remote rm origin # 远程主机改名 git remote rename origin neworigin ``` ## 1.4 添加和撤销操作 ``` # 显示有变更的文件 git status # 该文件内容恢复到上个commit状态 git checkout -- <file> # 所有文件恢复到上个commit状态 git checkout . # 修改的该文件放入暂存区 git add <file> # 所有修改的文件放入暂存区 git add . # 取消add操作,保留文件的修改 git reset HEAD <file> # 取消所有的add操作 git reset HEAD . # 添加commit信息 git commit -m 'your commit message' #回退所有内容到上一个版本 git reset HEAD^ #向前回退到第3个版本 git reset HEAD~3 # 将本地的状态回退到和远程的一样 git reset origin/master # 回退到某个版本 git reset 版本号 注意:reset命令有3种方式: 1> git reset –mixed:此为默认方式,不带任何参数的git reset,即时这种方式,它回退到某个版本,只保留源码,回退commit和index信息(需要git add ., git commit -m "xx") 2> git reset –soft:回退到某个版本,只回退了commit的信息,不会恢复到indexfile一级。如果还要提交,直接commit即可(git add . 内容不会丢,可以直接git commit -m "xxx") 3> git reset –hard:彻底回退到某个版本,本地的源码也会变为上一个版本的内容(丢弃所有内容) ``` ## 1.5 代码提交 ``` # commit信息 git commit -m "first commit" # 如果代码没有任何新变化,则用来改写上一次commit的提交信息 git commit --amend -m [message] # 本地只是修改commit的信息,没有新的文件更改 git commit --amend "xxxxx" # 本地修改,但是有新的文件需要添加 git log //找到回退到的版本号xxx git reset xxx //然后修改文件 git add . git commit -m "xxx" # 修改已经提交到远程的commit信息 git commit --amend 'xxx2' //先本地修改commit信息(git reset xxx等方式也可以),然后再强制推上去,慎用 git push --force origin master # 回退某个文件到某个版本 git log test.php git reset 9aa51d89799716aa68cff3f30c26f8815408e926 test.php ``` ## 1.6 分支操作 ``` # 列出所有本地分支 git branch # 列出所有远程分支 git branch -r # 列出所有本地分支和远程分支 git branch -a # 创建分支 git branch test # 切换分支 git checkout test # 创建并切换分支 git checkout -b test # 切换到远程分支 git fetch git checkout -b test origin/test # 新建一个分支,指向指定commit git branch [branch] [commit] # 新建一个分支,指向某个tag git checkout -b [branch] [tag] # 合并指定分支到当前分支 git merge [branch] # 删除分支(分支已经被合并) git branch -d [branch-name] # 删除分支(分支还没合并,强制删除掉) git branch -D [branch-name] # 批量删除分支方法 git branch |grep 'branchName' |xargs git branch -D # 删除远程分支 git branch -dr [origin/test] git push origin :master git push origin --delete master # 选择一个commit,将该commit改动下的代码合并进当前分支 git cherry-pick [commit] ``` ## 1.7 查看信息 ``` # 显示有变更的文件 git status # 显示当前分支的版本历史 git log # 显示commit历史,以及每次commit发生变更的文件 git log --stat # 显示某个文件的版本历史,包括文件改名 git log --follow [file] git whatchanged [file] # 显示指定文件相关的每一次diff git log -p [file] # 显示指定文件是什么人在什么时间修改过 git blame [file] # 显示暂存区和工作区的差异 git diff # 显示工作区与当前分支最新commit之间的差异 git diff HEAD # 显示两次提交之间的差异 git diff [first-branch]...[second-branch] # 显示某次提交的元数据和内容变化 git show [commit] # 显示某次提交发生变化的文件 git show --name-only [commit] # 显示某次提交时,某个文件的内容 git show [commit]:[filename] # 显示当前分支的最近几次提交,可以看到你使用了什么操作 git reflog ``` ## 1.8 pull操作 ``` # 取回远程主机某个分支的更新,再与本地的指定分支合并 git pull <远程主机名> <远程分支名>:<本地分支名> # 取回origin主机的next分支,与本地的master分支合并 git pull origin next:master # 如果远程分支是与当前分支合并,则冒号后面的部分可以省略。 git pull origin next # 建立追踪关系(git会自动在本地分支和远程分支之间建立一种追踪关系,默认本地分支和远程分支同名,例如next->origin:next) git branch --set-upstream master origin/next ``` ## 1.9 push操作 ``` # 把本地库的所有内容推送到远程库上 git push <远程主机名> <本地分支名>:<远程分支名> # 推送操作,如果省略远程分支名,则表示将本地分支推送与之存在”追踪关系”的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。 git push origin master # 将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了 git push -u origin master #不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机 git push --all origin # 如果远程主机的版本比本地版本更新,推送时Git会报错,要求先在本地做git pull合并差异,然后再推送到远程主机。这时,如果你一定要推送,可以使用--force选项,这样做会覆盖掉远程上比你新的版本。 git push --force origin master ``` ## 1.10 tag操作 ``` # 展示标签 git tag # 打标签和注释 git tag -a v0.1.2 -m "0.1.2版本" # 给指定的commit打标签 git tag -a v0.1.1 9fbc3d0 # git push 操作不会将tag上传到服务器,需要单独上传,将v0.1.2标签提交到git服务器 git push origin v0.1.2 # 将本地所有标签一次性提交到git服务器 git push origin --tags # 删除标签 git tag -d v0.1.2 # 删除远程的tag git push origin --delete tag <tagname> ``` # 2. 其他一些汇总 ## 2.1 github上初始一个项目 创建一个新的仓库,并上传到github ``` echo "# ceshi" >> README.md git init git add README.md git commit -m "first commit" git remote add origin [email protected]:archer-wong/ceshi.git git push -u origin master ``` 使用一个已有的仓库,并上传到github ``` git remote add origin [email protected]:archer-wong/ceshi.git git push -u origin master ``` ## 2.2 重命名远程分支(先删除远程分支,重命名本地分支,最后提交一个新的远程分支) ``` git push --delete origin devel git branch -m devel develop git push origin develop ``` ## 2.3 cherry-pick中出现冲突解决方法 ``` git status #查看有哪些冲突 vim xxx.php #手动解决冲突的文件 git add xxx.php git commit -m "xxx" git push origin develop ``` ## 2.4 git中window和Linux换行符问题 不同的操作系统中使用的换行符是不同的,参考如下 ``` Windows/Dos CRLF \r\n Linux/Unix LF \n MacOS CR \r ``` 当我们使用git管理版本的时候,如果有人在windows上开发,有人在linux上开发者,很可能你就会遇到行尾结束符问题,可以参考设置以下两项 1> 设置autocrlf 提交时转换为LF,拉取时转换为CRLF(windows上设置) git config --global core.autocrlf true 提交时转换为LF,拉取时不转换(linux上设置) git config --global core.autocrlf input 这样可以保证版本库里面是LF换行符,linux上使用LF, windows上迁出后使用的是CRLF 2. 开启safecrlf检查 Git提供了一个换行符检查功能(core.safecrlf),可以在提交时检查文件是否混用了不同风格的换行符。这个功能的选项如下: - false - 不做任何检查 - warn - 在提交时检查并警告 - true - 在提交时检查,如果发现混用则拒绝提交 建议使用最严格的 true 选项。core.autocrlf git config --global core.safecrlf true ## 2.5 .gitignore文件 .gitignore 配置文件用于配置不需要加入版本管理的文件 1、语法: ``` 所有空行或者以 # 开头的行都会被 Git 忽略。 可以使用标准的 glob 模式匹配。 匹配模式可以以(/)开头防止递归。 匹配模式可以以(/)结尾指定目录。 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。 ``` ``` 所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号(*)匹配零个或多个任意字符; [abc]匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c); 问号(?)只匹配一个任意字符; 如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。 使用两个星号(*) 表示匹配任意中间目录,比如a/**/z 可以匹配 a/z, a/b/z 或 a/b/c/z等。 ``` 2、示例: ``` # 忽略 .a 文件 *.a # 否定忽略 lib.a, 尽管已经在前面忽略了 .a 文件 !lib.a # 仅在当前目录下忽略 TODO 文件, 但不包括子目录下的 subdir/TODO /TODO # 忽略 build/ 文件夹下的所有文件 build/ # 忽略 doc/notes.txt, 不包括 doc/server/arch.txt doc/*.txt # 忽略所有的 .pdf 文件 在 doc/ directory 下的 doc/**/*.pdf ``` GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表,你可以在https://github.com/github/gitignore 找到它. 3、.gitignore不生效问题 如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提交: ``` git rm -r --cached . git add . git commit -m 'update .gitignore' ``` ## 2.6 平时采用的git管理模式 平时开发流程,每一个feature新建一个分支,然后在该分支开发完后,进行rebase操作,然后切换到主分支进行merge操作 ``` git branch -b feature-xxx //在master分支新建并切换分支,在feature-xxx完成代码,然后add,commit git checkout master git pull origin master git checkout feature-xxx git rebase master git checkout master git merge --no-ff feature-xxx git push origin master ``` rebase过程中产生冲突的解决方法 ``` 查看冲突的文件 git diff 然后手动解决冲突 git status 将冲突文件放入暂存区 git add vendor/composer/autoload_real.php 继续rebase操作 git rebase --continue ``` ## 2.7 分支合并的总结 参考地址:https://yanhaijing.com/git/2017/07/14/four-method-for-git-merge/ 在git中合并分支有三种方法,分别是merge,rebase,cherry-pick,而其中merge又有三种区别fast-forward,no-ff,squash ### 2.7.1 merge操作 1、fast-forward 如果待合并的分支在当前分支的下游,也就是说没有分叉时,会发生快速合并,从test分支切换到master分支,然后合并test分支 ``` git checkout master git merge test ``` 这种方法相当于直接把master分支移动到test分支所在的地方,并移动HEAD指针 ![](http://markdown.archerwong.cn/2019-01-02-04-02-10_1.gif) 2、no-ff 如果我们不想要快速合并,那么我们可以强制指定为非快速合并,只需加上--no-ff参数 ``` git checkout master git merge –no-ff test ``` 这种合并方法会在master分支上新建一个提交节点,从而完成合并 ![](http://markdown.archerwong.cn/2019-01-02-04-02-38_2.gif) 3、squash svn的在合并分支时采用的就是这种方式,squash会在当前分支新建一个提交节点 squash和no-ff非常类似,区别只有一点不会保留对合入分支的引用 ``` git checkout master git merge –squash test ``` ![](http://markdown.archerwong.cn/2019-01-02-04-03-02_3.gif) ### 2.7.2 rebase操作 当要合并两个分叉的分支时,merge的方式是将待合入分支和当前分支不同的部分,在当前分支新建节点,如下图所示 ![](http://markdown.archerwong.cn/2019-01-02-04-03-06_4.png) rebase与merge不同,rebase会将合入分支上超前的节点在待合入分支上重新提交一遍,如下图,B1 B2会变为B1’ B2’,看起来会变成线性历史 ![](http://markdown.archerwong.cn/2019-01-02-04-03-10_5.png) ### 2.7.3 cherry-pick 你想把哪个节点merge过来就把哪个节点merge过来,其合入的不是分支而是提交节点