Удалите конфиденциальные данные, хранящиеся в файлах eclipse /.history из разных (непроверенных) коммитов [дубликатов]

Когда ваши пути include разные

Ошибки компоновщика могут произойти, если заголовочный файл и связанная с ним общая библиотека (файл .lib) не синхронизируются. Позволь мне объяснить.

Как работают линкеры? Линкер соответствует объявлению функции (объявленному в заголовке) с его определением (в общей библиотеке) путем сравнения их подписи. Вы можете получить ошибку компоновщика, если компоновщик не найдет определение функции, которое идеально подходит.

Возможно ли получить ошибку компоновщика, даже если объявление и определение, похоже, совпадают? Да! Они могут выглядеть одинаково в исходном коде, но это действительно зависит от того, что видит компилятор. По сути, вы можете столкнуться с такой ситуацией:

// header1.h
typedef int Number;
void foo(Number);

// header2.h
typedef float Number;
void foo(Number); // this only looks the same lexically

Обратите внимание, что хотя обе декларации функций выглядят одинаково в исходном коде, но они действительно различаются в зависимости от компилятора.

Вы можете спросить, как это получается в такой ситуации? Включите пути, конечно! Если при компиляции разделяемой библиотеки путь include приводит к header1.h, и вы в конечном итоге используете header2.h в своей собственной программе, вы оставите царапины на своем заголовке, задаваясь вопросом, что произошло (каламбур).

Пример того, как это может произойти в реальном мире, объясняется ниже.

Дальнейшая разработка с примером

У меня есть два проекта: graphics.lib и main.exe. Оба проекта зависят от common_math.h. Предположим, что библиотека экспортирует следующую функцию:

// graphics.lib    
#include "common_math.h" 

void draw(vec3 p) { ... } // vec3 comes from common_math.h

И затем вы идете вперед и включаете библиотеку в свой собственный проект.

// main.exe
#include "other/common_math.h"
#include "graphics.h"

int main() {
    draw(...);
}

Boom! Вы получаете ошибку компоновщика, и вы понятия не имеете, почему она терпит неудачу. Причина в том, что общая библиотека использует разные версии одного и того же include common_math.h (я сделал это очевидным здесь в этом примере, включив другой путь, но это может быть не всегда так очевидно. Возможно, путь include отличается в настройки компилятора).

Обратите внимание, что в этом примере компоновщик сказал бы вам, что не смог найти draw(), когда на самом деле вы знаете, что он явно экспортируется библиотекой. Вы могли часами царапать себе голову, думая, что пошло не так. Дело в том, что компоновщик видит другую подпись, потому что типы параметров немного отличаются. В этом примере vec3 является другим типом в обоих проектах в отношении компилятора. Это может произойти из-за того, что они происходят из двух немного разных файлов include (возможно, включенные файлы поступают из двух разных версий библиотеки).

Отладка компоновщика

DUMPBIN - ваш друг, если вы используете Visual Studio. Я уверен, что другие компиляторы имеют другие подобные инструменты.

Процесс выглядит следующим образом:

  1. Обратите внимание на странное искаженное имя, указанное в ошибке компоновщика. (например, draw @ graphics @ XYZ).
  2. Выгрузите экспортированные символы из библиотеки в текстовый файл.
  3. Найдите экспортированный символ, представляющий интерес, и обратите внимание, что искаженное имя
  4. Обратите внимание на то, почему искаженные имена оказались разными. Вы могли бы видеть, что типы параметров различны, хотя они выглядят одинаково в исходном коде.
  5. Причина, почему они разные. В приведенном выше примере они различаются из-за разных файлов include.

[1] По проекту я имею в виду набор исходных файлов, которые связаны друг с другом для создания либо библиотеки, либо исполняемого файла .

РЕДАКТИРОВАТЬ 1: Переписать первый раздел, который будет легче понять. Пожалуйста, прокомментируйте ниже, чтобы сообщить мне, нужно ли что-то еще исправлять. Спасибо!

284
задан Roberto Tyley 10 December 2013 в 00:35
поделиться

10 ответов

Для всех практических целей, первое вещь, о которой вы должны беспокоиться, - ИЗМЕНЕНИЕ ВАШИХ ПАРОЛЕЙ! Из вашего вопроса неясно, является ли ваш репозиторий git полностью локальным или у вас еще есть удаленный репозиторий; если он удален и не защищен от других, у вас есть проблема. Если кто-то клонировал этот репозиторий, прежде чем исправить это, у вас будет копия ваших паролей на их локальной машине, и вы не сможете заставить их обновить свою «фиксированную» версию, если она уйдет из истории. Единственная безопасная вещь, которую вы можете сделать, - это изменить свой пароль на что-то еще, где бы вы его ни использовали.


С этим в сторону, вот как это исправить. GitHub ответил именно на этот вопрос в качестве FAQ :

Примечание для пользователей 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, а другие клонировали этот удаленный репозиторий, теперь вы находитесь в ситуации, когда вы переписываете историю. Когда другие пытаются снести ваши последние изменения после этого, они получат сообщение о том, что изменения не могут быть применены, потому что это не ускоренная перемотка вперед.

Чтобы исправить это, им придется либо удалить существующий репозиторий, либо повторно клонировать его , или следуйте инструкциям в разделе «ВОССТАНОВЛЕНИЕ ОТ РЕЖИМА UPSTREAM» в git-rebase manpage .


В будущем, если вы случайно совершите некоторые изменения с конфиденциальной информацией, но вы замечаете, прежде чем нажимать на удаленный репозиторий, есть несколько простых исправлений. Если вы последний коммит является тем, кто добавляет конфиденциальную информацию, вы можете просто удалить конфиденциальную информацию n, а затем запустите:

git commit -a --amend

Это изменит предыдущую фиксацию с внесенными вами новыми изменениями, включая полное удаление файлов, выполненное с помощью git rm. Если изменения вернулись в историю, но все же не были перенесены в удаленный репозиторий, вы можете сделать интерактивную перезагрузку:

git rebase -i origin/master

Это открывает редактор с фиксациями, которые вы сделали со своего последнего общего предка с удаленным репозиторием. Измените «pick» на «редактировать» на любых строках, представляющих фиксацию с конфиденциальной информацией, и сохраните и закройте. Git проведет изменения и оставит вас в месте, где вы можете:

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

Для каждого изменения с конфиденциальной информацией. В конце концов, вы вернетесь в свою ветку, и вы можете спокойно нажать новые изменения.

366
ответ дан snovelli 24 August 2018 в 03:36
поделиться
2
ответ дан b01 24 August 2018 в 03:36
поделиться
9
ответ дан Ciro Santilli 新疆改造中心 六四事件 法轮功 24 August 2018 в 03:36
поделиться

Я рекомендую этот скрипт Дэвида Андерхилла, работавший как прелесть для меня.

Он добавляет эти команды в дополнение к фильтру-ветке natacado, чтобы очистить беспорядок, который он оставляет:

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

Полный скрипт (весь кредит Дэвиду Андерхиллу)

#!/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
files=$@
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
16
ответ дан Jason Goemaat 24 August 2018 в 03:36
поделиться

Чтобы быть ясным: принятый ответ правильный. Сначала попробуйте. Тем не менее, это может быть излишне сложным для некоторых случаев использования, особенно если вы столкнулись с такими неприятными ошибками, как «фатальная: плохая ревизия - пустая» или действительно не заботятся об истории вашего репо.

Альтернативой будет:

  1. cd к базовой ветви проекта
  2. Удалить чувствительный код / ​​файл
  3. rm -rf .git / # Удалить все git-данные из вашего кода
  4. Перейдите в github и удалите репозиторий
  5. Следуйте этому руководству, чтобы подтолкнуть ваш код к новому репозиторию, как обычно - https: // help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/

Это, конечно, удалит все фиксации ветвей истории, а также проблем как с вашим реестром github, так и с местным реестром git. Если это неприемлемо, вам придется использовать альтернативный подход.

Назовите это ядерным вариантом.

8
ответ дан lostphilosopher 24 August 2018 в 03:36
поделиться

Вы можете использовать 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- забыть-blob /

Он исчезнет из всех коммитов вашей истории, reflog, тегов и т. д.

Я сталкиваюсь с той же проблемой время от времени, и каждый раз, когда я должен возвращаться к этому сообщению и другим, вот почему я автоматизировал процесс.

Кредиты вкладчикам из Stack Overflow, которые позволили мне собрать это вместе

4
ответ дан nachoparker 24 August 2018 в 03:36
поделиться

Итак, это выглядит примерно так:

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

Удалить кеш для отслеживаемого файла из git и добавить этот файл в список .gitignore

1
ответ дан przbadu 24 August 2018 в 03:36
поделиться

Изменение паролей - хорошая идея, но для процесса удаления паролей из истории вашего репо я рекомендую BFG Repo-Cleaner , более быструю и простую альтернативу git-filter-branch, явно предназначенную для удаление личных данных из Git repos.

Создайте файл private.txt, в котором перечислены пароли и т. д., которые вы хотите удалить (одна запись в строке), а затем выполните следующую команду:

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

Все файлы под пороговым размером (по умолчанию 1 МБ) в истории вашего репо будут отсканированы, и любая соответствующая строка (которая не входит в ваш последний commit] будет заменена на строку " *** REMOVED ***». Затем вы можете использовать git gc для удаления мертвых данных:

$ git gc --prune=now --aggressive

BFG обычно на 10-50 раз быстрее, чем запуск git-filter-branch, и опции упрощены и адаптированы к этим двум распространенным операциям, случаи:

  • Удаление сумасшедших больших файлов
  • Удаление паролей, учетных данных и amp; другие личные данные

Полное раскрытие: я являюсь автором BFG Repo-Cleaner.

68
ответ дан Roberto Tyley 24 August 2018 в 03:36
поделиться

Использовать ветвь фильтра:

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
5
ответ дан Stephen Rauch 24 August 2018 в 03:36
поделиться

Вот мое решение в windows

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

git push - force

убедитесь, что путь верен, иначе он не будет работать

Надеюсь, это поможет

6
ответ дан vertigo71 24 August 2018 в 03:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: