整理出一些常用的git命令。看这份文档之前,要求您对git的基本概念要清楚,比如”暂存区”, “工作区”, “本地分支”, “远程分支”,等等。
使用SSH Clone一个仓库,git clone git@<domain>.com:<username>/<repository>.git
或者 git clone ssh://<username>@<domain>.com/<repository>.git
。 例如:git clone git@github.com:JiaoJianbo/test.git
使用HTTPS Clone一个仓库,git clone https://<domain>.com:<username>/<repository>.git
例如:git clone https://github.com/JiaoJianbo/test.git
使用 HTTPS 除了速度慢以外,还有个最大的麻烦是每次 clone 和 push 都必须输入口令,但是在某些只开放 HTTP(S) 端口的公司内部就无法使用 SSH 协议就只能用 HTTPS 方式。
Clone 指定branch,使用-b
参数,git clone -b <branch name> <git URL>
Clone 指定tag,使用--branch
参数,git clone --branch <tag name> <git URL>
将所有改动加入暂存区 git add .
,执行前一定先使用 git status
查看一下。
从暂存区恢复到工作区 git reset HEAD <filename>
,对文件做的最新的所有改动都还在(包括已加入到暂存区的和加入暂存区后在工作区新做的修改)。
撤销工作区的改动 git checkout -- <filename>
注意--
后面有空格。其实就是让这个文件回到最近一次git commit
或者 git add
时的状态,无论工作区是修改还是删除。但是前提是该文件曾经被add
过或者commit
过,一个未曾加入过版本控制的新文件则不起作用。
撤销工作区和暂存区中所有文件的改动 git reset --hard HEAD
, 即将HEAD指到最近的一次commit。注意:那些已加入到暂存区还没有提交的改动也会被撤销,当然对未曾加入过版本控制的新文件则不影响。如果误操作了,不想撤销暂存区的改动,那么去搜索一下git fsck --lost-found
的具体用法。
查看所有的commit记录 git log
或者 git log --pretty=oneline
,还有 git log --graph --pretty=oneline --abbrev-commit
如果分屏显示,空格:下一页,B:上一页,Q:退出
撤销commit的修改(但是没有push) git reset HEAD^
或者 git reset --hard HEAD^
, 注:HEAD^
是上一个版本,HEAD^^
是上两个版本, HEAD~10
是上10个版本。撤销后已修改的内容还在,只是回退到工作区。
回退到某个版本 git reset --hard <commit id>
, commit id 没必须要写全,一般写前五位就可以了,commit id 可以使用 git log
或者 git reflog
去查看。
删除某个文件的 git 记录以及磁盘上文件本身 git rm <filename>
, 或者分两步,先手动删除磁盘上的文件,然后再git add <filename>
将 git 记录删除。但是直到 commit 才算正式生效。
删除 git 跟踪记录,但是想保留磁盘上的文件本身,使用 git rm --cached <filename>
,下面有详细介绍。
查看某个文件由谁在什么时候做了什么改动 git blame <filename>
查看工作区中某个文件跟版本库中的差别 git diff HEAD -- <filename>
。git diff
比较的是工作区尚未暂存的文件的改动,即比较的是工作区和暂存区之间的差异。如果之前没有暂存过,那比较的就是工作区跟版本库(最后一次 commit)之间的差异。因此,在执行完 add 操作后再执行 git diff
什么也没有。git diff --cached
或者 git diff --staged
比较的是暂存区和版本库中的差别。
创建并切换到新分支 git checkout -b <branch-name>
, git branch
查看分支,git branch <branch-name>
创建分支, git checkout <branch-name>
切换分支。
删除分支 git branch -d <branch-name>
git pull
实际上是 fetch
和 merge
的合并操作。
拉取远端分支(本地不存在的) git checkout -b <local-branch-name> origin/<remote-branch-name>
,如果拉取不成功,可以先尝试 git fetch
。git fetch
只是把远程内容下载到本地,并不会合并到本地,即不会改变工作区的内容。如果想查看下载下来的内容可以使用 git checkout origin/<branch-name>
。
推送一个本地分支到远端 git push origin <branch-name>
推送一个本地分支(远端不存在的) git push --set-upstream origin <branch-name>
建立本地分支与远端分支的链接 git branch --set-upstream-to=origin/<remote-branch-name> <local-branch-name>
查看所有本地分支和远程分支的对应关系 git branch -vv
查看所有分支的当前状态 git branch -av
在本地创建远程地址库的别名 git remote add origin <remote-repository>
, 例如:git remote add origin https://github.com/JiaoJianbo/jiaojianbo.github.io.git
查看远程库的详细信息 git remote -v
多分支工作时注意以下场景:
场景一:
- 在分支 A 修改,不 commit (可以使用 git add 加入暂存区)。
- 此时在分支 A 的基础上,创建分支 B。之前在分支 A 上修改的内容也会带到分支 B。
- 在分支 B 上接着修改,但仍然不提交。又切回分支 A。
- 此时,在分支 B 做的修改,在分支 A 仍然可以看到。
场景二:
- 在分支 A 修改,不 commit (可以使用 git add 加入暂存区)。
- 此时在分支 A 的基础上,创建分支 B。之前在分支 A 上修改的内容也会带到分支 B。
- 在分支 B 上接着修改,然后 commit。
- 切回分支 A。此时分支 A 上的内容是最后一次 commit 的,切换到分支 B 之前做的修改全没了。
结论:工作区和暂存区,没有分支的概念,对所有分支是共享的。只有 commit 后,修改的内容才会进入具体分支版本库,并且清空工作区和暂存区。
多人合作时,每次要 push 时,注意先 pull, 再 merge, 再 push。
git merge dev
将 dev 分支合并到当前分支,或者在 dev 分支上执行 git rebase <target-branch>
也会将 dev 分支合并到目标分支上,如果有冲突,解决完冲突,再执行 git rebase --continue
。注意:两个 merge 和 rebase 执行的时候,所在当前分支的区别。还有,一定不要对一个公共的分支做 rebase 操作 rebase 操作可以把本地未 push 的分叉提交历史整理成直线。
舍弃 rebase git rebase --abort
2019-03-29 更新
前面上传项目时,将 eclipse 自动生成的 .project
和 .classpath
也都上传了。现在由 eclipse 换成 STS,结果这两种文件都发生了改变。
想忽略这两种文件的改动,于是乎将 .project
和 .classpath
加入 .gitignore
文件,结果并没有起作用。又想到莫非是这些文件在子目录下,于是改为 **/.project
和 **/.classpath
,但是仍然没有起作用。
最后,终于找到了一个解决办法。使用 git rm --cached [filepath]
命令,删除 git 的跟踪记录,文件仍然保留再工作区。
同样,也删除 .classpath 之后,最终显示修改的文件就是我想要提交的了。
git rm <fileName>
删除暂存区或分支上的文件,同时工作区也不需要这个文件。
git rm --cached <fileName>
删除暂存区或分支上的文件,但是文件继续在工作区,不被版本控制。后续可以将该文件添加到 .gitignore 文件。
参考:
git rm与git rm –cached
Git忽略提交规则 - .gitignore配置运维总结
Git tag 操作
列出已有的 tag:git tag
打一个 tag(默认打在最后一次 commit 上):git tag -a [tagName] -m "my comments"
给指定的某个 commit 号加tag:git tag -a [tagName] 9fceb02 -m "my comments"
查看指定 tag 的详细信息:git show [tagName]
推送单个本地 tag:git push origin [tagName]
推送本地所有 tag:git push origin --tags
删除本地 tag:git tag -d [tagName]
删除远端 tag:git tag push origin :refs/tags/[tagName]
Git stash 操作
应用场景:
-
当你现在正在分支 A 上开发,但是突然需要修复一个 bug,但是目前分支 A 上的改动你又不想丢弃或者提交(参考上面的场景一、二,如果工作区和暂存区的改动不提交或者丢弃,都会被带到其他分支,并将最终被提交)。那么此时就可以使用
git stash
将所有工作区和暂存区的改动存储起来,然后再切换到其他分支去修复 bug。 -
由于疏忽,本应该在个人自己分支开发的内容,却在公共的 dev 分支上进行了开发,需要重新切回到自己分支上进行开发。可以用
git stash
将内容保存至堆栈中,切回到自己分支后,使用git stash pop
或者git stash apply
恢复已修改的内容即可。
将所有未提交的修改(工作区和暂存区)保存至堆栈中:git stash
,此时工作区和暂存区清空
为 git stash 添加一些注释:git stash save <comments>
查看当前 stash 中的所有内容:git stash list
将当前 stash 中的内容弹出,并应用到当前分支上: git stash pop
, 该命令当前最近保存的(先进后出)内容恢复到工作区,并删除保存记录。
git stash apply
将堆栈中的内容应用到当前目录,不同于 git stash pop,该命令不会将内容从堆栈中删除,也就说该命令能够将堆栈的内容多次应用到工作目录中,适应于多个分支的情况。
git stash drop <stash-name>
从堆栈中移除某个指定的 stash 记录。
git stash clear
清除堆栈中的所有内容。
git stash show -p stash@{0} | git apply -R
取消之前所应用的 stash 的修改
git stash branch
基于最近的 stash 创建分支。
参考:
3 Git 工具 - 储藏(Stashing)
git stash详解
git 分支重命名
- 重命名远程分支对应的本地分支名
git branch -m oldName newName
- 删除远程分支
git push -delete origin oldName
- 上传新命名的本地分支
git push origin newName
- 修改本地分支和远程分支的关联
git branch --set-upstream-to origin/newName
自动为多个repository 创建新分支的 shell 脚本
#!/bin/bash
BASE_DIR="/home/bobby/gittest/"
GIT_BASE_PREFIX="git@github.com:JiaoJianbo/"
GIT_BASE_SUFFFIX=".git"
ARTIFACT_LIST=(
dubbo-zookeeper
jiaojianbo.github.io
learning
#testJTopo
springcloud-tutorial
)
SOURCE_BRANCH="master"
TARGET_BRANCH="1.0_release"
for i in $(seq 0 $[${#ARTIFACT_LIST[@]}-1]); do
if [$i -eq ${#ARTIFACT_LIST[@]} ]; then
echo "!!! No more artifact !!!"
exit 0
fi
e=${ARTIFACT_LIST[$i]}
echo ""
echo -e "\e[32m\e[1m*************************************\e[0m"
echo -e "\e[32m\e[1m** "$e" **\e[0m"
echo -e "\e[32m\e[1m*************************************\e[0m"
echo "###1. clone project ###"
git clone -b master $GIT_BASE_PREFIX$e$GIT_BASE_SUFFFIX $BASE_DIR$e
echo "###2. enter project folder ###"
cd $BASE_DIR$e
echo "###3. switch to source branch ###"
git checkout $SOURCE_BRANCH && git pull
echo "###4. create new branch ###"
echo "create new branch $TARGET_BRANCH starting..."
git checkout -b $TARGET_BRANCH
echo "###5. replace version in pom.xml ###"
sed -i "s/1.0.0-SNAPSHOT/1.0.0-release/g" pom.xml
echo "###6. commit changes ###"
git add pom.xml && git commit -m "create $TARGET_BRANCH branch"
echo "###7. push to remote ###"
git push --set-upstream origin $TARGET_BRANCH
sleep 2;
done