Git技巧汇总
编辑提交
查看当前HEAD最近一次提交
git show
# 或
git log -n1 -p
修改提交信息
# commit message 错误
git commit --amend --only -m "new message" # 如果已经push,可以修改这次提交然后强制push,但是多人项目不推荐。
# 用户名邮箱错误
git commit --amend --author "new author <[email protected]>
修改所有的历史,参考git ilter-branch
命令。
从一个提交移除一个文件
git checkout HEAD^ <file>
git add -A
git commit --amend
如果已经push,可以修改然后强制push。
删除最后一次提交
# 已经push到远程仓库可以执行以下,这个多人项目不推荐,会造成已经拉取的用户的commit历史混乱
git reset HEAD^ --hard
git push -f <remote> <branch>
# 本地仓库没有推送到远程
git reset --soft HEAD@{1}
回滚本地以及远程仓库的提交
# 这个命令非常危险,一般不建议使用,尤其是多人项目
git reset <commit> --hard
git push -f origin HEAD
删除任意提交
# 同样非常危险,一般不建议使用
git rebase --onto <bad commit>^ <bad commit>
git push -f <remote> <branch>
推送修改后的提交(amended commit)到远程仓库被拒绝
To https://github.com/yourusername/repo.git
! [rejected] mybranch -> mybranch (non-fast-forward)
error: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
rebasing(见下面)和修正(amending)会用一个新的提交(commit)代替旧的,所以如果之前你已经往远程仓库上推过一次修正前的提交(commit),那你现在就必须强推(force push)。确保在同一个分支
git push -f <remote> <branch>
硬重置(hard reset)之后恢复
使用Git的时候需要知道一点,只要是commit了的内容,都会有日志记录,都是可以恢复的,可以通过git reflog
查看,找到硬重置(git reset --hard
)之前的commit,然后重新重置一次。
git reset --hard <commit>
清空所有的commit
# 这个命令有多危险我就不废话了
git update-ref -d HEAD
以新增一个commit的方式还原一个commit的修改
git revert <commit>
暂存
把暂存内容添加到上一次提交
git commit --amend
暂存一个新文件的一部分而不是全部
git add --patch <file> # -p 简写,针对已track文件,打开交互模式后使用s选项来分割提交
git add -N <file> # untrach文件需要加-N,打开交互模式使用e选项手动选择添加的行
未暂存
未暂存的文件移动到新分支
git checkout -b <branch>
未暂存的文件到另一个已经存在的分支
git stash
git checkout <branch>
git stash pop
丢弃本地所有未提交的修改
git checkout -f
需要重置某个特殊文件
git reset <file>
分支
快速切换到上一个分支
git checkout -
删除已经合并的分支
git branch --merged | grep -v '*' | xargs -n 1 git branch -d
本地分支关联远程分支信息
git branch -vv
重命名本地分支
git branch -m <new name>
从错误的分支拉取了内容,或把内容拉取到了错误的分支
reflog大法好
git reflog # 获取错误之前的commit
git reset --hard <commit> # 然后硬重置到之前的commit
扔掉本地的提交,与远程分支保持一致
首先确定没有推送到远程仓库,git status
会显示你领先(ahead)源(origin)多少个提交:
(master)$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 2 commits.
# (use "git push" to publish your local commits)
#
然后
git fetch --all && git reset --hard origin/master
提交更改到新分支,却错误提交到了master
git checkout <new branch> # 先基于当前的master创建一个新分支但切换过去
git reset --hard HEAD^ # 重置master到上一次提交
git checkout <new branch> # 检出新分支继续工作
不小心删除了分支
reflog大法好
git reflog # 查看删除操作之前的commit
git reset --hard <commit> # 然后硬重置到之前的commit
删除分支
# 删除远程分支
git push --delete <remote> <branch>
# 或
git push <remote> :<branch>
# 删除本地分支
git branch -D <branch>
从别人正在工作的远程分支检出一个分支
首先,从远程分支拉取所有分支
git fetch --all
然后从远程分支检出到本地分支
git checkout --track origin/<branch>
# --trach 是git checkout -b <branch> <remote>/<branch>的简写
合并
撤销rebase或merge
Git在进行危险操作的时候会把原始的HEAD保存在一个叫ORIG_HEAD的变量里。无论是用rebase还是merge进行合并,合并了一个错误的分支, 或者完成不了一个进行中的合并,都可以把分支恢复到rebase/merge前的状态。
git reset --hard ORIG_HEAD
安全merge策略
git merge --no-ff --no-commit <branch>
# --no-commit 执行合并(merge)但不自动提交, 给用户在做提交前检查和修改的机会
# --no-ff 会为特性分支(feature branch)的存在过留下证据, 保持项目历史一致
其他
clone所有子模块
git clone --recursive <url>
如果已经克隆,需要更新的话
git submodule update --init --recursive
从stash拿出某个文件
git checkout <stash@{n}> -- <file>
把某一个分支导出为文件
git bundle create <bundle-file> <branch>
导入
git clone <bundle-file> <repo> -b <branch>
执行rebase之前自动stash
git rebase --autostash
详细展示一行中的差异
git diff --word-diff
清除满足gitignore中模式的文件
git clean -X -f
显示branch1有branch2没有的commit
git log <branch1> ^<branch2>
clone指定分支
git clone -b <branch> --single-branch <url>
恢复已删除的tag
先找到无法访问的tag,记下哈希值
git fsck --unreachable | grep tag
然后进行恢复
git update-ref refs/tags/<tag> <hash>
从Git中删除文件,但保留该文件在当前目录
git rm --cached <file>
统计分支提交数量
git rev-list --count <branch>
打包未跟踪的文件
git ls-files --others --exclude-standard -z | xargs -0 tar rvf ./untracked.tar
总之,reflog大法好。