簡體   English   中英

我可以從git分支刪除多少個文件?

[英]How much can i delete a file from a git branch?

目前 許多 線程在SO關於不同部門跟蹤不同的文件。 由於git也簡化了部署,因此人們嘗試將部署特定的秘密文件添加到內部分支中,並且會出現那些線程中討論的問題。 一種可能的建議解決方案是使用submodule 我寧願避免這種情況。 因此,通過擴展此方法,使腳本可以合並我的私有分支,而無需考慮.branchownfiles列出的秘密文件的.branchownfiles

看來效果很好,但是提出了一個關於在git中刪除文件的問題: git mergeprivate合並到master時抱怨刪除的文件,即使該文件從未參與過與master相關的提交:“在HEAD中刪除並在私人的”

這是您可以看到的過程:

i@my % git init
Initialized empty Git repository in /here/there/.git/
i@my % echo 'hello' > 'start.txt'
i@my % git add start.txt
i@my % git commit -m 'started'
[master (root-commit) 32d41f5] started
 1 file changed, 1 insertion(+)
 create mode 100644 start.txt

i@my % git checkout -b private
Switched to a new branch 'private'
i@my % echo 'this is secret' > a_secret.txt
i@my % echo a_secret.txt > .branchownfiles
i@my % echo .branchownfiles >> .branchownfiles
i@my % git add a_secret.txt
i@my % git add .branchownfiles
i@my % git commit -m 'a secret file added'
[private c2e174f] a secret file added
 2 files changed, 3 insertions(+)
 create mode 100644 .branchownfiles
 create mode 100644 a_secret.txt

i@my % git checkout master
Switched to branch 'master'
i@my % git-merge-with-care.sh private
Automatic merge went well; stopped before committing as requested
rm '.branchownfiles'
rm 'a_secret.txt'
Success
# this is basically a `git merge` followed by two `git rm` for two files.
# so i suppose .branchownfiles and a_secret.txt never should leave anything in `master`
# but my assumption is not true..
i@my % git commit
[master 916c14b] Merge branch 'private'

i@my % git checkout private
Switched to branch 'private'
i@my % echo 'changed in private, should change in public too' > start.txt
i@my % echo 'secret changed too' > a_secret.txt
i@my % git add -u
i@my % git commit -m 'secret changed'
[private dc8938a] secret changed
 2 files changed, 2 insertions(+), 2 deletions(-)

i@my % git checkout master
Switched to branch 'master'
i@my % git-merge-with-care.sh private
# now my question arise.
CONFLICT (modify/delete): a_secret.txt deleted in HEAD and modified in private. Version private of a_secret.txt left in tree.
# git merge complains about a_secret.txt an knows it deleted in HEAD. Why?!
Automatic merge failed; fix conflicts and then commit the result.
Trying to fix conflicts for branch limited files
a_secret.txt: [b]
Remerge with ours strategy
CONFLICT (modify/delete): a_secret.txt deleted in HEAD and modified in private. Version private of a_secret.txt left in tree.
Automatic merge failed; fix conflicts and then commit the result.
a_secret.txt: needs merge
rm 'a_secret.txt'
Success

我的腳本仍然有效,因為它在合並之前刪除了這些文件。 但是我想知道為什么git回憶起a_secret.txt盡管它從未提交過此分支? 有沒有一種方法可以實現git merge --no-commit后跟git rm的某種方式,git永遠不會回憶起這些已刪除的文件? 我的意思是git merge但是能夠將一些文件添加到索引目錄。

我的方法安全嗎? 如果我git rm一些文件,然后git后來回憶起這些文件以前在這里,git仍然有關於這些文件的一些信息。 什么樣的數據,它在哪里? 有人可以通過僅限於master分支的訪問來找到a_secret.txt的內容嗎?

這是我的git-merge-with-care.sh

#!/bin/env zsh

ls -d .git 2>/dev/null 1>&2
if [ $? != 0 ]; then
    echo "error: run this from root of project"
    exit 1
fi

if [ $# != 1 ]; then
    echo "usage: $0 <private branch>"
    exit 1
fi

current_branch=$(git branch -q | sed -n -e 's/^* //p')
from_branch=$1 #private branch
into_branch=master #public branch

if [ $current_branch != $into_branch ]; then
    echo "error: merge while out of $into_branch branch"
    exit 1
fi

new_files=$(git diff -z --name-only --diff-filter=A $into_branch $from_branch)
changed_files=$(git diff -z --name-only --diff-filter='M|T' $into_branch $from_branch)
branch_files=$(git show $from_branch:.branchownfiles)
git merge --no-commit --no-ff $from_branch

# fix conflict with strategy
if [ $? != 0 ]; then
    echo "Trying to fix conflicts for branch limited files"
    failing=false
    git diff -z --name-only --diff-filter=U  | while IFS= read -r -d $'\0' f; do
        { grep -x -q "$f" <<<"$branch_files" && echo "$f: [b]"; } || { [ $f != ".branchownfiles" ] && echo "$f: [!]" && failing=true; }
    done
    git merge --abort
    if $failing; then
        echo "Merge aborted because of merge conflicts"
        exit 2
    else
        echo "Remerge with ours strategy"
        git merge --no-commit $from_branch -s recursive -X ours --no-ff
        if [ $? != 0 ]; then
            # conflits for deleted files in merger but added again from mergee
            conflicting_files=$(git diff -z --name-only --diff-filter=U)
            # echo "$conflicting_files" | sort
            # echo "$new_files" | sort

            if grep -q "$(echo \"$conflicting_files\" | sort -z)" <<<"$(echo \"$new_files\" | sort -z)"; then
                xargs -0 <<<"$conflicting_files" -I'{}' git rm --ignore-unmatch '{}'
                [[ x`git diff --diff-filter=U` == 'x' ]] || exit 5
            fi
        fi
    fi
fi

# remove files added from private branch but are restricted to private branch
xargs -0 -I'{}' <<<$new_files sh -c "grep -x -q '{}' <<<\"$branch_files\" && [ -e '{}' ] && git rm -rf '{}'"

# bring back public files overwritten bye private branch data
xargs -0 -I'{}' <<<"$changed_files" sh -c "grep -x -q '{}' <<<\"$branch_files\" && git checkout HEAD '{}'"
echo "Success"
exit 0

當您合並兩個分支時,這兩個提交都可以從合並提交中到達。 因此,如果您有權訪問母版,則可以在合並之前秘密訪問所有內容。 這也是git認為文件已刪除的原因。

如果我簽出該回購協議並僅獲得master分支,則可以執行git checkout master^2並且您實際上在秘密分支上。

嘗試運行git merge-base master private 它將給“添加的秘密文件”提交。 提交和主服務器之間的區別之一是主服務器上缺少文件(a_secret,.branchownfiles)。 所以git的東西一定是在master上刪除的,因為那個提交是master的祖先。 沒錯 那就是信息的來源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM