it-swarm.dev

Git 히스토리에서 민감한 파일과 커밋 제거

Git 프로젝트를 GitHub에 배치하고 싶지만 민감한 데이터가 포함 된 특정 파일 (사용자 이름 및 비밀번호, capistrano의 경우 /config/deploy.rb)이 포함되어 있습니다.

이 파일 이름을 . gitignore에 추가 할 수 있지만 Git 내에서 기록을 제거하지는 않습니다.

또한 /.git 디렉토리를 삭제하여 다시 시작하고 싶지 않습니다.

Git 히스토리에서 특정 파일의 all 흔적을 제거하는 방법이 있습니까?

319
Stefan

모든 실질적인 목적으로, 당신이 걱정해야 할 first 것은 암호 변경! git 저장소가 완전히 로컬인지는 확실하지 않습니다. 또는 다른 곳에 원격 저장소가 있는지 여부 원격이고 다른 사람으로부터 보호되지 않으면 문제가있는 것입니다. 이 문제를 해결하기 전에 해당 리포지토리를 복제 한 사용자는 로컬 컴퓨터에 암호 복사본을 갖게되며 기록에서 나온 "고정"버전으로 강제로 업데이트 할 수있는 방법이 없습니다. 당신이 할 수있는 유일한 안전한 방법은 당신이 사용한 다른 곳으로 암호를 바꾸는 것입니다.


그 방법으로 문제를 해결하는 방법은 다음과 같습니다. GitHub가 그 질문에 정확하게 대답했습니다 :

Windows 사용자를위한 참고 사항 :이 명령에서 작은 따옴표 대신 큰 따옴표 ( ")를 사용하십시오

git filter-branch --index-filter \
'git update-index --remove filename' <introduction-revision-sha1>..HEAD
git Push --force --verbose --dry-run
git Push --force

이 코드를 GitHub와 같은 원격 저장소로 푸시하고 다른 사람들이 해당 원격 저장소를 복제 한 후에는 이제 기록을 다시 작성하는 상황에 처해 있습니다. 이후에 다른 사람이 최신 변경 사항을 풀다운하면 변경 사항을 빨리 적용 할 수 없으므로 적용 할 수 없다는 메시지가 표시됩니다.

이 문제를 해결하려면 기존 리포지토리를 삭제하고 다시 복제하거나 git-rebase 맨 페이지 의 "UPSTREAM REBASE에서 복구"아래의 지침을 따라야합니다.


나중에 민감한 정보로 실수로 일부 변경 사항을 커밋하지만 before 원격 저장소로 푸시하는 경우 몇 가지 쉬운 수정 사항이 있습니다. 마지막 커밋이 민감한 정보를 추가하는 것이면 민감한 정보를 제거하고 다음을 실행하면됩니다.

git commit -a --amend

git rm로 수행 한 전체 파일 제거를 포함하여 새로 변경 한 내용으로 이전 커밋을 수정합니다. 변경 사항이 히스토리로 다시 되돌아가도 여전히 원격 저장소로 푸시되지 않은 경우 대화식 리베이스를 수행 할 수 있습니다.

git rebase -i Origin/master

그러면 원격 저장소를 사용하여 마지막 공통 조상 이후로 커밋 한 편집기가 열립니다. 민감한 정보가있는 커밋을 나타내는 행에서 "pick"을 "edit"로 변경하고 저장하고 종료하십시오. 힘내 변경 사항을 안내하고 당신이 할 수있는 자리에 당신을 떠날 것입니다 :

$EDITOR file-to-fix
git commit -a --amend
git rebase --continue

민감한 정보로 변경 될 때마다. 결국 지점에 다시 도착하게되며 새로운 변경 사항을 안전하게 푸시 할 수 있습니다.

398
natacado

비밀번호를 변경하는 것이 좋습니다. 그러나 리포지토리에서 비밀번호를 제거하는 과정에서 BFG Repo-Cleaner 는 _git-filter-branch_를 제거하기 위해 명시 적으로 설계된 더 빠르고 간단한 대안 인 것이 좋습니다. Git repos의 개인 데이터.

제거 할 비밀번호 등을 나열하는 _private.txt_ 파일을 작성하고 (한 줄에 한 항목 씩) 다음 명령을 실행하십시오.

_$ Java -jar bfg.jar  --replace-text private.txt  my-repo.git
_

리포지토리의 임계 ​​값 크기 (기본적으로 1MB) 미만의 모든 파일이 검사되고 일치하는 문자열 ( 최신 커밋에없는)은 문자열 "*** REMOVED ***". 그런 다음 _git gc_를 사용하여 죽은 데이터를 정리할 수 있습니다.

_$ git gc --Prune=now --aggressive
_

BFG는 _git-filter-branch_를 실행하는 것보다 일반적으로 10-50 배 빠르며 옵션은 다음 두 가지 일반적인 사용 사례에 따라 단순화되고 조정됩니다.

  • 미친 큰 파일 제거
  • 비밀번호, 자격 증명 및 기타 개인 데이터 제거

전체 공개 : 저는 BFG Repo-Cleaner의 저자입니다.

82
Roberto Tyley

David Underhill의 this script 을 추천합니다.

Natacado의 필터 브랜치와 함께 다음 명령을 추가하여 남은 혼란을 정리합니다.

rm -rf .git/refs/original/
git reflog expire --all
git gc --aggressive --Prune

전체 스크립트 (David Underhill의 모든 크레딧)

#!/bin/bash
set -o errexit

# Author: David Underhill
# Script to permanently delete files/folders from your git repository.  To use 
# it, cd to your repository's root and then run the script with a list of paths
# you want to delete, e.g., git-delete-history path1 path2

if [ $# -eq 0 ]; then
    exit 0
fi

# make sure we're at the root of git repo
if [ ! -d .git ]; then
    echo "Error: must run this script from the root of a git repository"
    exit 1
fi

# remove all paths passed as arguments from the history of the repo
[email protected]
git filter-branch --index-filter \
"git rm -rf --cached --ignore-unmatch $files" HEAD

# remove the temporary history git-filter-branch
# otherwise leaves behind for a long time
rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --Prune

다음으로 변경하면 마지막 두 명령이 더 잘 작동 할 수 있습니다.

git reflog expire --expire=now --all && \
git gc --aggressive --Prune=now
19
Jason Goemaat

GitHub로 푸시 한 경우 강제 푸시로 충분하지 않은 경우 리포지토리를 삭제하거나 지원 센터에 문의하십시오

강제로 1 초 후에 강제로 밀어도 아래 설명 된 것처럼 충분하지 않습니다.

유일하게 유효한 조치는 다음과 같습니다.

  • 비밀번호와 같이 변경 가능한 자격 증명이 유출 된 것은 무엇입니까?

    • 예 : 비밀번호를 즉시 수정하고 더 많은 OAuth 및 API 키 사용을 고려하십시오!
    • 아니오 (알몸 사진) :

      • 리포지토리의 모든 문제가 해결되는지 걱정하십니까?

        • 아니오 : 저장소를 삭제하십시오.
        • 예:

          • 연락처 지원
          • 누출이 당신에게 매우 중요하다면, 누설 가능성을 줄이기 위해 저장소 가동 중지 시간을 기꺼이 할 수있는 시점까지 비공개 GitHub 지원이 귀하에게 응답하기를 기다리는 동안

다음과 같은 이유로 1 초 후에 강제로 충분하지 않습니다.

그러나 강제 푸시 대신 저장소를 삭제하면 커밋은 API에서도 즉시 사라지고 404를 제공합니다 (예 : https://api.github.com/repos/cirosantilli/test-dangling-delete/commits/8c08448b5fbf0f891696819f3b2b2d653f7a3824 같은 이름의 다른 리포지토리를 다시 생성하더라도 작동합니다.

이것을 테스트하기 위해 레포를 만들었습니다 : https://github.com/cirosantilli/test-dangling

git init
git remote add Origin [email protected]:cirosantilli/test-dangling.git

touch a
git add .
git commit -m 0
git Push

touch b
git add .
git commit -m 1
git Push

touch c
git rm b
git add .
git commit --amend --no-edit
git Push -f

GitHub에서 매달려 커밋을 제거하는 방법?

명확하게 : 허용되는 답변이 맞습니다. 먼저 해보십시오. 그러나 특히 '치명적 : 잘못된 개정-자두 비우기'와 같은 눈에 띄지 않는 오류가 발생하거나 실제로 리포지토리의 역사에 관심이없는 경우 일부 사용 사례에서는 불필요하게 복잡 할 수 있습니다.

대안은 다음과 같습니다.

  1. 프로젝트의 기본 분기에 cd
  2. 민감한 코드/파일 제거
  3. rm -rf .git/# 코드에서 모든 자식 정보를 제거하십시오
  4. Github로 이동하여 저장소를 삭제하십시오.
  5. 이 안내서에 따라 평소와 같이 코드를 새 저장소에 푸시하십시오. https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command- 라인 /

이것은 물론 모든 커밋 히스토리 브랜치와 github 저장소 및 로컬 git 저장소 모두에서 문제를 제거합니다. 이것이 용납 할 수없는 경우 다른 방법을 사용해야합니다.

이것을 핵 옵션이라고 부릅니다.

9
lostphilosopher

창문에 내 해결책이 있습니다.

git filter-branch --tree-filter "rm -f 'filedir/filename'"HEAD

자식 푸시-강제

그렇지 않으면 경로가 올바른지 확인하십시오.

나는 그것이 도움이되기를 바랍니다

7
vertigo71

filter-branch를 사용하십시오 :

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch *file_path_relative_to_git_repo*' --Prune-empty --tag-name-filter cat -- --all

git Push Origin *branch_name* -f
6

git forget-blob를 사용할 수 있습니다.

사용법은 git forget-blob file-to-forget입니다. 여기에서 더 많은 정보를 얻을 수 있습니다

https://ownyourbits.com/2017/01/18/completely-remove-a-file-from-a-git-repository-with-git-forget-blob/

그것은 당신의 역사, 참조, 태그 등의 모든 커밋에서 사라질 것입니다.

나는 때때로 같은 문제에 부딪 쳤고,이 포스트와 다른 사람들로 돌아와야 할 때마다 프로세스를 자동화 한 이유입니다.

Stack Overflow의 기여자에게이 크레딧을 제공 할 수있는 크레딧

5
nachoparker

나는 이것을 현재까지 몇 번해야했다. 한 번에 하나의 파일에서만 작동합니다.

  1. 파일을 수정 한 모든 커밋 목록을 가져옵니다. 맨 아래에있는 것이 첫 번째 커밋입니다.

    git log --pretty=oneline --branches -- pathToFile

  2. 히스토리에서 파일을 제거하려면 첫 번째 커밋 sha1과 이전 명령의 파일 경로를 사용하여 다음 명령으로 채우십시오.

    git filter-branch --index-filter 'git rm --cached --ignore-unmatch <path-to-file>' -- <sha1-where-the-file-was-first-added>..

3
b01

따라서 다음과 같이 보입니다.

git rm --cached /config/deploy.rb
echo /config/deploy.rb >> .gitignore

Git에서 추적 된 파일에 대한 캐시를 제거하고 해당 파일을 .gitignore 목록에 추가하십시오.

3
przbadu

내 Android 프로젝트에서 app/src/main/res/values ​​/ 폴더에 분리 된 xml 파일로 admob_keys.xml이있었습니다. 이 민감한 파일을 제거하기 위해 아래 스크립트를 사용하여 완벽하게 작동했습니다.

git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch  app/src/main/res/values/admob_keys.xml' \
--Prune-empty --tag-name-filter cat -- --all
1
Ercan Duman