Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Git 如何修复错误的合并,并将正确的提交重放到固定的合并上?_Git_Git Filter Branch_Git Rewrite History_Git Rm - Fatal编程技术网

Git 如何修复错误的合并,并将正确的提交重放到固定的合并上?

Git 如何修复错误的合并,并将正确的提交重放到固定的合并上?,git,git-filter-branch,git-rewrite-history,git-rm,Git,Git Filter Branch,Git Rewrite History,Git Rm,几次提交之前,我在解析合并时意外地将一个不需要的文件(filename.orig)提交到了我的存储库中,直到现在我都没有注意到它。我想从存储库历史记录中完全删除该文件 是否可以重写更改历史记录,以便从一开始就不会将filename.orig添加到存储库中?这就是设计的目的。如果您的情况与问题中描述的情况不同,请不要使用此配方。此方法用于修复错误的合并,并将好的提交重放到固定的合并上。 虽然filter branch将执行您想要的操作,但这是一个相当复杂的命令,我可能会选择使用git-rebase

几次提交之前,我在解析合并时意外地将一个不需要的文件(
filename.orig
)提交到了我的存储库中,直到现在我都没有注意到它。我想从存储库历史记录中完全删除该文件


是否可以重写更改历史记录,以便从一开始就不会将
filename.orig
添加到存储库中?

这就是设计的目的。

如果您的情况与问题中描述的情况不同,请不要使用此配方。此方法用于修复错误的合并,并将好的提交重放到固定的合并上。

虽然
filter branch
将执行您想要的操作,但这是一个相当复杂的命令,我可能会选择使用
git-rebase
来执行此操作。这可能是个人喜好
filter branch
可以在一个稍微复杂的命令中完成,而
rebase
解决方案是一步一步地执行等效的逻辑操作

尝试以下配方:

#在错误合并位置创建并签出临时分支
git签出-b tmpfix
#删除错误添加的文件
git rm somefile.orig
#提交修改后的合并
修改最后一次提交
#回到主分支
切换到主分支
#将主分支重新移植到已更正的合并上
git-rebase-tmpfix
#删除临时分支
吉特分行-d tmpfix

(请注意,您实际上不需要临时分支,您可以使用“分离头”来完成此操作,但您需要记下由
git commit--amend
步骤生成的提交id,以提供给
git rebase
命令,而不是使用临时分支名称。)

如果此后您没有提交任何内容,只需
gitrm
文件和
gitcommit--amend

如果你有

git filter-branch \
--index-filter 'git rm --cached --ignore-unmatch path/to/file/filename.orig' merge-point..HEAD
将完成从
合并点
的每次更改,删除filename.orig并重写更改。使用
--ignore unmatch
意味着如果出于某种原因更改中缺少filename.orig,则该命令不会失败。这是本文示例部分中推荐的方法

Windows用户注意:文件路径必须使用前斜杠

您还可以使用:

git重置头文件/路径

这是最好的方法:

只需确保先备份文件的副本即可

编辑

审查期间,编辑被不幸拒绝。
请参阅下面的Neons帖子,它可能包含有用的信息


例如,要删除意外提交到git存储库中的所有
*.gz
文件:

$ du -sh .git ==> e.g. 100M
$ git filter-branch --index-filter 'git rm --cached --ignore-unmatch *.gz' HEAD
$ git push origin master --force
$ rm -rf .git/refs/original/
$ git reflog expire --expire=now --all
$ git gc --prune=now
$ git gc --aggressive --prune=now
那对我还是不起作用?(我目前使用的是git版本1.7.6.1)

不知道为什么,因为我只有一个主分支。不管怎么说,我终于把我的git回购真正清理干净了,我把它推到了一个新的空的、光秃秃的git存储库中

$ git init --bare /path/to/newcleanrepo.git
$ git push /path/to/newcleanrepo.git master
$ du -sh /path/to/newcleanrepo.git ==> e.g. 5M 
(是的!)

然后我将其克隆到一个新目录,并将其.git文件夹移到这个目录中。e、 g

$ mv .git ../large_dot_git
$ git clone /path/to/newcleanrepo.git ../tmpdir
$ mv ../tmpdir/.git .
$ du -sh .git ==> e.g. 5M 
(是啊!终于打扫干净了!)


在确认一切正常后,您可以删除
。/large\u dot\u git
。/tmpdir
目录(可能在几周或几个月后,以防万一……)

重写git历史记录需要更改所有受影响的提交ID,因此,参与该项目的每个人都需要删除旧的回购协议副本,并在清除历史记录后进行新的克隆。给it带来不便的人越多,您就越需要一个很好的理由来做这件事——您多余的文件并不会真的造成问题,但是如果您正在处理项目,如果您愿意的话,您最好清理Git历史记录

为了使其尽可能简单,我建议使用,这是一种比
git过滤器分支更简单、更快的替代方法
,专门用于从git历史记录中删除文件。在这里,它使您的生活更轻松的一种方式是,它在默认情况下处理所有引用(所有标记、分支等),但速度也更快

您应该仔细遵循以下步骤:-但核心部分是:下载(需要Java 6或更高版本)并运行以下命令:

$ java -jar bfg.jar --delete-files filename.orig my-repo.git
将扫描您的整个存储库历史记录,并删除所有名为
filename.orig
(不在您的存储库中)的文件。这比使用
git filter branch
做同样的事情要容易得多


全面披露:我是BFG回购清理器的作者。

为了将这一点添加到Charles Bailey的解决方案中,我刚刚使用git rebase-I从早期提交中删除了不需要的文件,它就像一个符咒。 步骤如下:

# Pick your commit with 'e'
$ git rebase -i

# Perform as many removes as necessary
$ git rm project/code/file.txt

# amend the commit
$ git commit --amend

# continue with rebase
$ git rebase --continue
简介:您有5种解决方案可用 原始海报上写着:

我不小心将一个不需要的文件提交到了我的存储库中 之前…我想从存储库历史记录中完全删除该文件

是吗 可以重写更改历史记录,以便永远不会删除
filename.orig
首先添加到存储库中

有许多不同的方法可以完全从中删除文件的历史记录 吉特:

  • 修正承诺
  • 硬重置(可能加上重设基准)
  • 非交互式重基
  • 交互式回扣
  • 过滤分支
  • 在原始海报的情况下,修改提交实际上不是一个选项 因为他后来又犯了几次罪 为了完整性,我还将向其他任何人解释如何做到这一点 想修改他们以前的承诺

    请注意,所有这些解决方案都涉及修改/重写历史记录/提交 以另一种方式,因此任何拥有提交旧副本的人都必须这样做 将其历史记录与新历史记录重新同步的额外工作。


    解决办法1:修订承诺 如果您不小心做了更改
    # Pick your commit with 'e'
    $ git rebase -i
    
    # Perform as many removes as necessary
    $ git rm project/code/file.txt
    
    # amend the commit
    $ git commit --amend
    
    # continue with rebase
    $ git rebase --continue
    
    git rm <file>
    git commit --amend --no-edit
    
    git reset --hard HEAD^
    
    git rm <file>
    git commit --amend --no-edit
    git rebase --continue
    
    git diff master@{1}
    
    git diff master@{1}
    
    #!/bin/bash
    if [[ $1 == "" ]]; then
        echo "Usage: $0 FILE_OR_DIR [remote]";
        echo "FILE_OR_DIR: the file or directory you want to remove from history"
        echo "if 'remote' argument is set, it will also push to remote repository."
        exit;
    fi
    FOLDERNAME_OR_FILENAME=$1;
    
    #The important part starts here: ------------------------
    
    git filter-branch -f --index-filter "git rm -rf --cached --ignore-unmatch $FOLDERNAME_OR_FILENAME" -- --all
    rm -rf .git/refs/original/
    git reflog expire --expire=now --all
    git gc --prune=now
    git gc --aggressive --prune=now
    
    if [[ $2 == "remote" ]]; then
        git push --all --force
    fi
    echo "Done."
    
    You should probably clone your repository first.
    
    Remove your file from all branches history:
    git filter-branch --tree-filter 'rm -f filename.orig' -- --all
    
    Remove your file just from the current branch:
    git filter-branch --tree-filter 'rm -f filename.orig' -- --HEAD    
    
    Lastly you should run to remove empty commits:
    git filter-branch -f --prune-empty -- --all
    
    touch empty
    git init
    git add empty
    git commit -m init
    
    # 92K   .git
    du -hs .git
    
    dd if=/dev/random of=./random bs=1m count=5
    git add random
    git commit -m mistake
    
    # 5.1M  .git
    du -hs .git
    
    git reset --hard HEAD^
    git reflog expire --expire=now --all
    git gc --prune=now
    
    # 92K   .git
    du -hs .git