git

本文总阅读量

git pull 强制覆盖本地

一般我们需要同步线上分支时,需要重新强制拉取线上分支覆盖到本地

1
2
3
4
5
6
7
8
# 从远程拉取所有内容
git fetch --all

# reset 本地代码
git reset --hard origin/master

# 重启拉取对齐
git pull

回退到某个分支

很多时候我们经常需要回退到某个分支,这时就需要git reset,为了保险起见,需要确保在执行git reset前,能知道当前分支的commit或者查看reflog的commit,确保有后悔药可以吃

1
git reset <commit> --hard

git reset简单粗暴,就是把索引指向某个commit,并做对应的操作,使用方法

1
git reset <commit>

具体参数定义如下:

1
2
3
4
5
--soft 回退后a分支修改的代码被保留并标记为add的状态(git status 是绿色的状态)
--mixed 重置索引,但不重置工作树,更改后的文件标记为未提交(add)的状态。默认操作。
--hard 重置索引和工作树,并且a分支修改的所有文件和中间的提交,没提交的代码都被丢弃了。
--merge --hard类似,只不过如果在执行reset命令之前你有改动一些文件并且未提交,merge会保留你的这些修改,hard则不会。【注:如果你的这些修改add过或commit过,merge和hard都将删除你的提交】
--keep --hard类似,执行reset之前改动文件如果是a分支修改了的,会提示你修改了相同的文件,不能合并。如果不是a分支修改的文件,会移除缓存区。git status还是可以看到保持了这些修改。

如果要reset到上个提交,可以直接写

1
git reset --hard HEAD^

移除git的某些commit

执行该命令,会撤销对应的提交,然后再重新提交一个新的提交(该操作可以撤销,如果使用reset则会直接回退到某个commit,除非有reflog记录或记得某个commit id,不然无法撤销).
再执行git revert前,必须执行

1
2
git diff <commit1> HEAD
git diff <commit1>..<commit2>

查看要撤销的代码是否正确,再使用 git revert 可以撤销指定的提交,要撤销一串提交可以用 .. 语法。 注意这是一个前开后闭区间,即不包括 commit1,但包括 commit2。

1
2
3
git revent <commit>
# 可以指定一个前开后闭的区间被移除
git revent <commit>...<commit>

另外一种移除git的某些commit方法

假设有commig v1,v2,v3,v4,v5共5个commit, 下面的操作会移除v3这个commit

1
2
3
4
5
6
# 从 v2 切分支出来
git checkout -b fixing v2
# 合并 v4,保持代码不变
git merge -s ours v4
# 合并 v5(也就是当前罪行的分支)
git merge master

git将一个分支完全覆盖另外一个分支

如下代码,把线上的master分支覆盖本地的develop分支

1
2
3
4
5
6
# 切换到develop
git checkout develop
# 指向origin/master
git reset --hard origin/master
# 强拉
git push -f

git hooks文件指定

git hook文件一般为bash.sh文件, 只要把文件放置于项目的.git/hooks下即可让该项目的git命令享用hook套餐

如果觉得每个项目都需要配置一次很麻烦, 则可以创建一个文件夹存放hooks文件,并调用全局命令git config --global core.hookspath xxx指定.

如果自己的电脑上有自己的项目和公司的项目, 想用两套hook文件, 也还是有办法的:

  • 1.首先自己的项目和公司的项目是在不同的文件夹里面, 比如我自己的项目在/home/so1n/github, 公司的项目在/home/so1n/xxx_gitlab下面.
  • 2.修改~/.gitconfig
    1
    2
    [includeIf "gitdir:~/xxx_gitlab/"]
    path = .gitconfig-xxx
  • 3.创建一个与上面path一样的文件~/.gitconfig-xxx,并写入如下配置, 指定该项目需要的hook文件
    1
    2
    [core]
    hookspath = ~/.git-hooks

    git禁止在master分支push和commit

    本小节来源
    作为管理者,在远端将master分支设为保护分支,可以从根源上杜绝直接推送到master的问题, 每个平台的选项有所不同.
    作为开发者,在本地的git hook中加配置可以做到在commit和push操作时做对应的检查.

禁止在master分支上Commit

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh

# 指定受保护的分支
protected_branch='master'

# 获取当前的分支
current_branch=$(git rev-parse --symbolic --abbrev-ref HEAD)

# 判断当前分支是否为受保护的分支, 如果是则打印警告, 并且退出
if [ "$protected_branch" == "$current_branch" ]; then
echo ".git/hooks: Do not commit to $current_branch branch"
exit 1
fi

在master分支上Commit时提示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/sh

protected_branch='master'
current_branch=$(git rev-parse --symbolic --abbrev-ref HEAD)

if [ "$protected_branch" == "$current_branch" ]; then
# 打印提示 并等待操作...
read -p "You're about to commit to master, is that what you intended? [y|n] " -n 1 -r </dev/tty
echo
# 如果是y则通过, 否则退出
if echo "$REPLY" | grep -E '^[Yy]$' >/dev/null; then
exit 0
fi
exit 1
fi

禁止推送到master分支

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/sh

protected_branch='master'
remote_branch_prefix="refs/heads/"
protected_remote_branch=$remote_branch_prefix$protected_branch

while read local_ref local_sha remote_ref remote_sha
do
if [ "$protected_remote_branch" == "$remote_ref" ]; then
echo ".git/hooks: Do not commit to $protected_branch branch"
exit 1
fi
done

exit 0

推送时如果commit消息包含WIP则禁止推送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/sh

protected_branch='master'
remote_branch_prefix="refs/heads/"
protected_remote_branch=$remote_branch_prefix$protected_branch

while read local_ref local_sha remote_ref remote_sha
do
if [ "$protected_remote_branch" == "$remote_ref" ]; then
read -p "You're about to push master, is that what you intended? [y|n] " -n 1 -r < /dev/tty
echo
if echo $REPLY | grep -E '^[Yy]$' > /dev/null
then
exit 0 # push will execute
fi
exit 1 # push will not execute
fi
done

exit 0
查看评论