Как навсегда предотвратить передачу определенной части файла в git?

Я клонировал удаленный репозиторий SVN с git -svn. Я изменил файл pom.xml в этом клонированном репо способом, который компилирует код. Эта настройка для меня исключительно. Таким образом, я не хочу возвращать изменения на дистанционное репо.

Есть ли способ предотвратить эту (частичную) смену файла на передачу в репо? Я знаю, что я мог бы использовать личную ветвь, но это означало бы определенные слияния накладных расходов. Существуют ли другие способы?

Я рассмотрел этот question и этот один, но они предназначены для довольно временных изменения.

Обновление: я также знаю возможности .gitignore, но это означало бы полностью исключить файл.

Ответ 1

EDIT: То, что вы просите, невозможно, я не видел "частичную" часть. Я знаю, что вы можете фиксировать только часть файлов, но вы не можете игнорировать часть файла. Вам нужно будет использовать трюк индекса обновления, чтобы избежать его в "статусе", и вам нужно будет хранить этот файл каждый раз, когда вы будете переустанавливать/слить с удаленного, а затем разблокировать изменения и игнорировать вашу модификацию с помощью update- индекс. Я не знаю, можете ли вы создать псевдоним git для последовательности команд git, поэтому с помощью одной команды вы можете сделать все эти 3 команды, чтобы избежать проблем с

используйте файл .gitignore и не нажимайте его на дистанционное репо: Игнорировать сам файл .gitignore

в .gitignore, вы должны иметь

 .gitignore
 path/to/pom.xml

a .gitignore файл может находиться в корне рабочего дерева или в любом подкаталоге, который вы хотите/нуждаетесь

Ответ 2

Там может быть возможность с фильтрами. Но это нужно изучить больше.

Начальная точка: выполните смазывание/очистить этот фильтр:

git config --global filter.versionUpdate.smudge 'sed "s/<version>14.5.0<\/version>/<version>14.5.FEATURE-15<\/version>/"'
git config --global filter.versionUpdate.clean 'sed "s/<version>FEATURE-15<\/version>/<version>14.5.0<\/version>/"'

Таким образом, при сопоставлении файл всегда будет таким же, как и фильтр.

Проблема: по-прежнему требуется расследование, как найти отфильтрованные файлы. Это не так заметно в рабочем каталоге.

Фильтр очистки Smudge

Ответ 3

Один из общих способов поделиться этим типом файла конфигурации:

  1. зафиксировать файл шаблона (например, pom.xml.template)
  2. игнорировать сам файл (например, добавить pom.xml в файл .gitignore)
  3. каждый пользователь может настроить этот файл в соответствии со своими потребностями

Вот несколько способов реализовать шаг 3.

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

Ответ 4

Может быть проще решить вашу проблему вне git. Вы можете определить свойство со значением по умолчанию в pom.xml, который каждый использует. А для вашей эксклюзивной настройки вы просто переопределяете свойство в ${user.home}/.m2/settings.xml или в командной строке Maven, используя -Dproperty=value. Или аналогичным образом вы можете создать другой профиль и активировать его на основе переменной среды, которую вы экспортируете, скажем, в ~/.bashrc.

Для git-решения я выполнил то, что вы хотите, с некоторой дисциплиной в правильном соблюдении рабочего процесса:

  1. Внесите изменения, относящиеся к настройке, в pom.xml (или другие файлы).
  2. Зафиксируйте изменения в git (только локально). В заголовке/сообщении коммита укажите, что изменения предназначены только для локального использования, например "ТОЛЬКО ЛОКАЛЬНО. НЕ ПОЛЬЗУЙТЕСЬ: остальная часть заголовка".
  3. Вытащить изменения из SVN, сделать локальные коммиты Git и т.д.
  4. Как только пришло время отменить ваши изменения обратно в SVN, сделайте
    1. git svn rebase получать новые коммиты из SVN, разрешать конфликты.
    2. git rebase -i svn/trunk (или какова ваша удаленная ветвь svn) (это запустит интерактивный перебаз всех ваших локальных изменений поверх SVN)
    3. В интерактивном редакторе задач rebase переместите свой локальный коммит в нижнюю часть.
    4. Сохраните задачу и выйдите из редактора задач.
    5. Устраните любые конфликты (их не должно быть, если вы не коснулись той же части вашего pom.xml (или другого локального файла) в других локальных коммитах).
  5. Запустите git svn dcommit --dry-run @~1 (или git svn dcommit --dry-run HEAD~1 в старом git), чтобы увидеть, что будет отправлено в репозиторий SVN; убедитесь, что ваши локальные коммиты отсутствуют в списке.
  6. Запустите git svn dcommit @~1 (или git svn dcommit HEAD~1), чтобы, наконец, отправить изменения в репозиторий SVN.
  7. git svn rebase чтобы получать новые коммиты из SVN.

Это может звучать сложно, но это довольно просто, когда вы привыкнете к этому. По сути, у вас есть одна (или более) локальная фиксация, которую вы никогда не отправляете в SVN. У меня не было ошибочно выдвинутого коммита более года, используя этот рабочий процесс с несколькими коммитами и репозиториями. Это довольно полезно, например, для некоторых локальных изменений только для отладки (хотя для этого лучше ввести переменную окружения или какой-то файл настроек).

Кроме того, это может быть улучшено с помощью ловушки pre-dcommit в git, который будет гарантировать, что изменения только локальные не будут dcommit'ed. К сожалению, я не вижу стандартного хука git-svn для этого, но можно использовать git-svn-hooks для их реализации.

Ответ 5

Это звучит для меня как веский аргумент в пользу ловушки перед фиксацией. В вашей папке .git у вас должна быть папка hooks. Там могут быть некоторые образцы, но они игнорируются, поскольку имеют расширение .sample. Если вы добавите файл с именем "pre-commit" (без расширения), содержащий приведенный ниже скрипт, скрипт будет запускаться каждый раз, когда вы делаете коммит. Не забудьте сделать сценарий исполняемым, запустив "chmod ug + x pre-commit".

Я добавил несколько комментариев, объясняющих, что делает каждая строка, но, по сути, как бы вы ее использовали, вы бы поместили "#start" над кодом, который вы не хотите включать в ваши коммиты git, а затем "#end" под этим кодом. Вы можете использовать разные стартовые и конечные флаги в команде sed, просто убедитесь, что вы используете синтаксис комментариев для любого языка, на котором вы разрабатываете, чтобы компилятор их игнорировал. Когда вы в конце концов выполните коммит, произойдет следующее:

  1. Код посередине (включая флаги #start и #end) будет удален
  2. Файл будет зафиксирован без кода и флажков
  3. Затем код и флаги будут возвращены в вашу локальную копию файла

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

перед фиксацией

#!/usr/bin/env bash

echo "Running pre-commit hook..."

set -e
export PATH=$PATH:/usr/local/bin
exit_status=0

echo "Removing supercomments..."
# Get a list of files part of this commit
files=$(git diff --cached --name-status)

# Loop through each file
for f in $(echo $files | awk '{ print $2}')
do
        # Create a temp copy of the file
        cp ${f} ${f}.temp
        # Remove all chunks between '#start' and '#end'
        sed -i '/#start/,/#end/d' ${f}
        # Add the file with chunks removed
        git add ${f}
        # Replace file with temp file containing code you didn't want to comm
it
        cp ${f}.temp ${f}
done

echo "Hook completed!"

exit $exit_status

Пример использования:

test.txt

This is a file
It really just a test file

#start
This code is only relevant to me
When I eventually commit this file...
...please don't inclue all of this!
#end

This part of the file is important,
make sure it included in my next commit.

добавить & передайте test.txt:

git add test.txt
#

git commit -m "A great commit message."
# Running pre-commit hook...
# Removing supercomments...
# Hook completed!
# [master commit_id_1234] A great commit message.

test.txt (в commit_id_1234)

This is a file
It really just a test file


This part of the file is important,
make sure it included in my next commit.

test.txt (локальная копия после фиксации)

This is a file
It really just a test file

#start
This code is only relevant to me
When I eventually commit this file...
...please don't inclue all of this!
#end

This part of the file is important,
make sure it included in my next commit.

Примечание: Есть несколько нюансов в вашем вопросе для рассмотрения. Похоже, у вас есть набор кода, который вы хотите иметь в своих файлах, но только при локальной компиляции (я предполагаю, что вы в основном разрабатываете и тестируете свой код локально), но затем вы хотите иметь возможность зафиксировать этот код разработки и автоматически удалить ваш "только локально релевантный код" перед фиксацией. Хотя описанный выше хук должен делать именно это, имейте в виду, что часть "only-local-релевантного кода" не является версионной, поскольку она никогда не попадает в ваш удаленный репозиторий, когда вы в конечном итоге отправляете. Это может быть очевидно, но просто убедитесь, что вы в порядке с этим. Если что-то случится с вашей локальной копией, весь этот код, даже если он имеет отношение только к вам, может быть утерян и не может быть восстановлен путем простого клонирования репозитория.

Ответ 6

Хорошие идеи уже предложены. Prehooks кажется наиболее подходящим, пожалуй. Некоторые другие возможности для рассмотрения могут быть: - Форк репо и зафиксировать все изменения - Зафиксируйте отдельную ветку в том же репо и зафиксируйте - Есть локальный филиал только ваших личных различий, которые вы выбираете, когда проверяете, и проверяете перед регистрацией? - Применить файлы исправлений - снова, которые могут быть отменены перед проверкой (хотя проблематично)