使当前提交的唯一(初始)提交的Git仓库?

问题描述 投票:594回答:14

我现在有一个本地的Git仓库,这是我推到Github上库。

本地资源库拥有约10个提交,GitHub的仓库就是一个同步复制。

我想要做的就是从本地Git仓库中删除所有版本历史记录,这样仓库的当前内容显示为唯一的提交(而不是存储在库中的文件,因此旧版本)。

那么我想推动这些变化Github上。

我已经调查的Git变基,但是这似乎是更适合于去除特定版本。另一个潜在的解决方法是删除本地回购,并创建一个新的 - 尽管这可能会创造大量的工作!

ETA:但是也有一些未经跟踪特定目录/文件 - 如果可能的话,我想保持这些文件的untracking。

git github git-commit
14个回答
938
投票

这里的蛮力的方法。它也消除了存储库的配置。

注意:如果存储库有子模块,这并不工作!如果您使用的子模块,你应该使用例如interactive rebase

第1步:删除所有历史记录(请确保您有备份,这不能被还原)

cat .git/config  # note <github-uri>
rm -rf .git

步骤2:用仅在当前内容重建GIT中回购

git init
git add .
git commit -m "Initial commit"

步骤3:推GitHub的。

git remote add origin <github-uri>
git push -u --force origin master

1
投票

我想要做的就是从本地Git仓库中删除所有版本历史记录,这样仓库的当前内容显示为唯一的提交(而不是存储在库中的文件,因此旧版本)。

更概念性的答案:

git的自动垃圾收集旧提交如果没有标签/分支机构/裁判指向他们。所以,你只需要去除所有标签/分支,并创建一个新的孤儿提交,任何分支相关联 - 按照规定,您先给分支master指向该承诺。

旧的,不可达的提交随后将不会再被任何人,除非他们去低级别的Git命令挖看到。如果这对你来说是足够的,我也只是停在那里,并让自动GC做的工作时,它希望。如果你想摆脱他们马上就可以使用git gc(可能与--aggressive --prune=all)。对于远程git仓库,有没有办法让你强制,虽然,除非你有自己的文件系统shell访问。


0
投票

只要删除GitHub库,并创建一个新的。迄今为止最快,最简单,最安全的方法。毕竟,你有什么获得在当所有你想要的是主分支合并为单一提交接受的解决方案进行所有这些命令?


0
投票

干得好:

#!/bin/bash
#
# By Zibri (2019)
#
# Usage: gitclean username password giturl
#
gitclean () 
{ 
    odir=$PWD;
    if [ "$#" -ne 3 ]; then
        echo "Usage: gitclean username password giturl";
        return 1;
    fi;
    temp=$(mktemp -d 2>/dev/null /dev/shm/git.XXX || mktemp -d 2>/dev/null /tmp/git.XXX);
    cd "$temp";
    url=$(echo "$3" |sed -e "s/[^/]*\/\/\([^@]*@\)\?\.*/\1/");
    git clone "https://$1:$2@$url" && { 
        cd *;
        for BR in "$(git branch|tr " " "\n"|grep -v '*')";
        do
            echo working on branch $BR;
            git checkout $BR;
            git checkout --orphan $(basename "$temp"|tr -d .);
            git add -A;
            git commit -m "Initial Commit" && { 
                git branch -D $BR;
                git branch -m $BR;
                git push -f origin $BR;
                git gc --aggressive --prune=all
            };
        done
    };
    cd $odir;
    rm -rf "$temp"
}

此外此间举行:https://gist.github.com/Zibri/76614988478a076bbe105545a16ee743


-1
投票

我从我的项目只是删除.git文件夹,并通过的IntelliJ版本控制重返解决类似的问题。注:.git文件夹是隐藏的。可以在与ls -a终端查看它,然后使用rm -rf .git将其删除。


-1
投票

对于使用浅克隆命令git的克隆--depth 1个网址 - 它将只克隆库的当前HEAD


-2
投票

要删除最后从git的承诺,你可以简单地运行

git reset --hard HEAD^ 

如果你是从顶部移除多次提交,可以运行

git reset --hard HEAD~2 

除去最后两个提交。你可以增加数以去除更多的提交。

More info here.

Git tutoturial here提供了有关如何清除库的帮助:

要删除历史文件,并把它添加到的.gitignore,以确保它不会意外地重新提交。在我们的例子中,我们打算从GitHub的宝石库中删除Rake文件。

git clone https://github.com/defunkt/github-gem.git

cd github-gem

git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch Rakefile' \
  --prune-empty --tag-name-filter cat -- --all

现在,我们已经抹去的历史文件,我们确保我们不会意外地再次提交。

echo "Rakefile" >> .gitignore

git add .gitignore

git commit -m "Add Rakefile to .gitignore"

如果你感到快乐与仓库的状态,就需要强制推送更改覆盖远程仓库。

git push origin master --force

559
投票

这对我的作品(并保持子模块的工作),唯一的解决办法是

git checkout --orphan newBranch
git add -A  # Add all files and commit them
git commit
git branch -D master  # Deletes the master branch
git branch -m master  # Rename the current branch to master
git push -f origin master  # Force push master branch to github
git gc --aggressive --prune=all     # remove the old files

删除.git/总是会引起巨大的问题时,我有子模块。使用git rebase --root会在一定程度会引起冲突,我(因为我有很多的历史需要很长时间)。


88
投票

这是我偏爱的方法:

git branch new_branch_name $(echo "commit message" | git commit-tree HEAD^{tree})

这将创建一个新的分支与一个承诺,增加了在HEAD一切。它不会改变任何东西,所以它是完全安全的。


31
投票

另一种选择,这可能变成是一个大量的工作,如果你有很多的提交,是一个互动变基(假设你的Git版本为> = 1.7.12):git rebase --root -i

当呈现在编辑器中提交列表:

  • 更改“选择”到“改写”为第一次提交
  • 更改“选择”到“修正”隔提交

保存并关闭。 Git会启动垫底。

在最后你将有一个新的根犯这是所有它之后传来的那些的组合。

其优点是,你不必删除你的资料库,如果你有第二个想法,你总是有一个后备。

如果你确实想用核武器炸你的历史,重置主这个承诺并删除所有其他部门。


18
投票

larsmans提出的方法的变体:

保存untrackfiles列表:

git ls-files --others --exclude-standard > /tmp/my_untracked_files

保存您的git的配置:

mv .git/config /tmp/

然后,执行larsmans的第一步:

rm -rf .git
git init
git add .

恢复您的配置:

mv /tmp/config .git/

Untrack您未跟踪文件:

cat /tmp/my_untracked_files | xargs -0 git rm --cached

然后提交:

git commit -m "Initial commit"

最后推到你的资料库:

git push -u --force origin master

5
投票

你可以使用浅clones(GIT> 1.9):

git clone --depth depth remote-url

延伸阅读:http://blogs.atlassian.com/2014/05/handle-big-repositories-git/


4
投票

git filter-branch是主要的手术工具。

git filter-branch --parent-filter true -- @^!

--parent-filter得到读取标准父母应打印在标准输出上改写父母; UNIX true成功退出,并打印什么,所以:没有父母。 @^!Git shorthand for“头承诺,但不是其父母的任何”。然后删除所有其他裁判和推动在休闲。


4
投票

下面是改编自@Zeelot的答案的脚本。它应该来自所有分支,而不仅仅是主分支删除历史记录:

for BR in $(git branch); do   
  git checkout $BR
  git checkout --orphan ${BR}_temp
  git commit -m "Initial commit"
  git branch -D $BR
  git branch -m $BR
done;
git gc --aggressive --prune=all

它的工作为我的目的(我不使用子模块)。


2
投票

下面的方法是完全可重复的,所以没有必要再次运行克隆,如果双方都一致,只是对对方运行该脚本了。

git log -n1 --format=%H >.git/info/grafts
git filter-branch -f
rm .git/info/grafts

如果你再想把它清理干净,试试这个脚本:

http://sam.nipl.net/b/git-gc-all-ferocious

我写了一个脚本,“杀死历史”在库中的每个分支:

http://sam.nipl.net/b/git-kill-history

另见:http://sam.nipl.net/b/confirm

© www.soinside.com 2019 - 2024. All rights reserved.