0%

Git不常用解决方案

1、rebase和 merge 的区别:

git merge 会生成一个新得合并节点,而rebase不会.

如两个分支:test 和 master

  D---E test

 /

 A---B---C---F master

使用merge合并:

  D--------E

 /          \

 A---B---C---F----G   test, master

而使用rebase则:

 A---B---D---E---C'---F'   test, master

使用git pull时默认是merge, 加 –rebase参数使其使用rebase方式

1
git pull --rebase   

2、git如何忽略已经提交的文件

  • 首先将要忽略的文件或文件夹添加到 .gitignore 文件中

  • 停止追踪指定文件

    1
    2
    3
    4
    // 忽略单个文件
    git rm -r --cached [要忽略的文件/文件夹]
    // 忽略所有文件
    git rm -r --cached .
  • 推送到远程仓库

    1
    2
    3
    git add .
    git commit -m " commet for commit ....."
    git push

    然后其他开发人员pull之后, ignore规则就对其生效了.

3、git怎样删除未监视的文件untracked files

删除 untracked files:

1
git clean -f

连 untracked 的目录也一起删掉

1
git clean -fd

4、git上传本地库到远程仓库

1.拉取远程仓库

1
2
3
4
5
6
git clone git@gitlab.alibaba-inc.com:CMedia-iOS/YXWAliyunOSSModule.git
cd YXWAliyunOSSModule
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master

2.对于已存在的文件夹或仓库

1
2
3
4
5
6
cd existing_folder
git init
git remote add origin git@gitlab.alibaba-inc.com:CMedia-iOS/YXWAliyunOSSModule.git
git add .
git commit
git push -u origin master

5、git reset –hard 、git push –force之后如何恢复

1
2
3
4
5
//查找丢失的commit id
git reflog

//创建一个新的分支,在新的分支对丢失的commit id执行:
git cherry-pick 901a33f

6、如何删除历史记录里的大文件

适用于从一个git项目中,将体积较大的资源彻底从git中删除,包括历史提交记录。

如果仅仅在目录中删除一个文件是不够的,只要在提交记录中有这个文件,那么 .git 中就会有这个文件的信息。

用 filter-branch 可以强制修改提交信息,将某个文件的历史提交痕迹也抹去,就像从来没有过这个文件一样。

1.找出需要删除的大文件

先执行

1
git gc --prune=now

通过如下命令找到git中保存的大小排名前5的大文件

1
git verify-pack -v .git/objects/pack/pack-*.idx | sort -k 3 -g | tail -5

可以得到如下信息:

1
2
3
4
5
b36ba8c5e4749183794705473321ea312b3a409d blob   46486053 11171997 77887787 1 80c1c35362872c8da6e02117a670902efcdce987
8d1dd2ee60e08b0385fc217a25ea33f36119d694 blob   62475792 7355607 206667227
267a27fef686fbdfbd25210fe36c8a224a5c1a10 blob   81598760 24710676 214022834
abe16d4278121f1a3eacdf3a966326bfb581a741 blob   109294368 28516988 98937450
80c1c35362872c8da6e02117a670902efcdce987 blob   195184864 37268015 40619772

最后一条就是最大的文件记录,80c1c35362872c8da6e02117a670902efcdce987 是其id,通过如下命令找到该文件的位置

1
git rev-list --objects --all | grep 80c1c35362872c8da6e02117a670902efcdce987

可以得到如下结果

1
80c1c35362872c8da6e02117a670902efcdce987 AWU3dControl/Frameworks/UnityFramework.framework

AWU3dControl/Frameworks/UnityFramework.framework 即为文件的位置,一般情况下这里的文件位置应该为文件夹/文件夹/文件的格式

2. 重写所有commit

1
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch Applet/Features/Libs/*.framework" --prune-empty --tag-name-filter cat -- --all

到这里,历史记录中已经没有该文件了。不过运行 filter-branch 产生的日志还是会对该文件有引用,所以还需要运行以下几条命令,把该文件的引用完全删除:

1
2
3
git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

push

1
git push -f --all

可以通过以下命令查看.git文件夹大小

1
du -sh .git

3.脚本封装

可以写一个名为largelist.sh的shell脚本存放在.git文件下用以快速查找体积较大的对象内容; (清理后需要删除largelist.sh脚本);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 #!/bin/bash
#set -x 
IFS=$'\n';
 
# 默认值是 10个  可以一次性展示更多 就修改第15行代码  | head -n 30 或者更多
objects=`git verify-pack -v objects/pack/pack-*.idx | grep -v chain | sort -k3nr | head`
 
echo "All sizes are in kB. The pack column is the size of the object, compressed, inside the pack file."
 
output="size,pack,SHA,location"
for y in $objects
do
    # extract the size in bytes
    size=$((`echo $y | cut -f 5 -d ' '`/1024))
    # extract the compressed size in bytes
    compressedSize=$((`echo $y | cut -f 6 -d ' '`/1024))
    # extract the SHA
    sha=`echo $y | cut -f 1 -d ' '`
    # find the objects location in the repository tree
    other=`git rev-list --all --objects | grep $sha`
    #lineBreak=`echo -e "\n"`
    output="${output}\n${size},${compressedSize},${other}"
done
 
echo -e $output | column -t -s ', '

创建完成后需要给 largelist.sh 文件赋予执行权限; 并执行文件

1
2
chmod +x largelist.sh
./largelist.sh

7、git stash clear之后的恢复

1
2
3
git fsck --lost-found, 找出刚才删除的提交对象和文件对象, 里面是一个一个的 dangling commit commitId
git show commitId一个一个的查看修改的内容, 找到了我们需要恢复的commitId之后
git stash apply commitId直接恢复就可以了

8、配置命令的别名

  • 命令行设置 git 的配置 alias
    1
    git config --global alias.<简化的字符> 原始命令
    如: 设置获取状态
    1
    git config --global alias.st status #代表输入 git st 就代表 git status
  • 手动配置 ~/.gitconfig 文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
          pl = pull
    st = status
    ci = commit
    co = checkout
    br = branch
    df = diff
    unstage = reset HEAD --
    lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Cres et' --abbrev-commit
    last = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Cr eset' --abbrev-commit -1 HEAD
    [core]
    excludesfile = /Users/mac/.gitignore_global
    editor = /usr/local/bin/vim
    [push]
    default = simple
    [difftool "sourcetree"]
    cmd = opendiff \"$LOCAL\" \"$REMOTE\"
    path =
    [mergetool "sourcetree"]
    cmd = /Applications/Sourcetree.app/Contents/Resources/opendiff-w.sh \"$LOCAL\" \"$REMOTE\" -ancestor \"$BASE\" -merge \"$MERGED\"
    trustExitCode = true