Как удалить папку, но сохранить все подфодлеры и файлы только в одной ветке git? - PullRequest
1 голос
/ 14 мая 2019

Я настраиваю ветку git, которая должна иметь структуру каталогов, отличную от остальных. Файлы все одинаковые, однако, по сути, все они должны быть перемещены на уровень выше. Есть много файлов, и я не знаю, как их полностью переместить с помощью git.

В настоящее время это выглядит примерно так:

Root Directory
    |
    - Main Folder
    |    |
    |     - Sub Folder 1 with a lot of subfolders and files
    |    |
    |     - Sub Folder 2 with a lot of other subfodlers and files
    |
    - A couple of random files

Что я хочу закончить:

Root Directory
    |
    - Sub Folder 1 with a lot of subfolders and files
    |
    - Sub Folder 2 with a lot of other subfodlers and files
    |
    - A couple of random files

Однако это изменение должно быть исключительно в одной ветви.

Как бы я это сделал?

Ответы [ 2 ]

2 голосов
/ 14 мая 2019

Перед началом работы необходимо знать несколько полезных фоновых вещей:

  • Git хранит только файлы , а не папки.
  • Каждый коммит Git хранит полный снимок из всех ваших файлов, а точнее, всех ваших совершенных файлов.Это то, что Git называет неотслеживаемыми файлами * площадка .(У него есть еще одно старое имя, которое теперь предполагается использовать для чего-то другого, но иногда некоторые вещи будут ссылаться на кеш . Все три имени относятся к одному и тому же.)

Git хранит эти файлы в коммитах .Git действительно все о коммитах.Каждый коммит пронумерован, но не в виде простого последовательного способа «коммит № 1, коммит № 2, ...».Вместо этого каждый коммит получает уникальный хеш-идентификатор , причем хеш-идентификаторы выглядят совершенно случайными и не связаны с предыдущими коммитами.Эти хэш-идентификаторы представляют собой большие уродливые строки букв и цифр, такие как 83232e38648b51abbcbdb56c94632b6906cc85a6, из которых git log выплевывает.

Поскольку каждый файл находится в каждый коммит, важно, чтобы Git сохранял их так, чтобы сразу не использовать весь ваш дисковод.Таким образом, сохраненные файлы сжимаются и, кроме того, shared для разных коммитовGit может сделать это, потому что для хранения файлов используется специальный формат Git-only, freeze -ried.Файлы в этой форме не могут быть изменены , но могут использоваться совместно.Это означает, что никакая существующая фиксация не может быть изменена . Каждый коммит в вашем хранилище архивируется, более или менее постоянно. 1 Думайте о коммитах как о постоянных (они в основном есть) и неизменных.Они являются историей, хранящейся в хранилище.


1 Возможно удалить коммиты, но это немного сложно, а Git обычно не делаетон тоже сразу - так что даже если вы думаете коммит ушел и не можете сразу его найти, он, вероятно, все еще там.


Выполняется работа

Теперь, это все хорошо и хорошо для архивирования, но эти только для чтения сублимированные файлы совершенно бесполезны для фактического выполнения любой работы .Для этого Git предоставляет то, что Git называет рабочим деревом .Это просто место, где вы выполняете свою работу.

В рабочем дереве Git извлекает лиофилизированные файлы из некоторых коммитов, повторно их гидрируя, чтобы они имели свою обычную повседневную форму.Теперь вы можете видеть и работать с этими файлами.Вы просто выбираете один коммит - обычно, последний коммит в некоторой ветви - и говорите: Получите мне этот коммит , и Git сделает это.Он находит фиксированный коммит и перечисляет все файлы в нем:

  • main-folder/sub1/file1: Ага , говорит Git, это рабочее дерево не имеет main-folder,давайте сделаем один.И у него нет sub1 в main-folder, который я только что сделал, давайте сделаем это тоже.Теперь я могу создать новый файл main-folder/sub1/file1.
  • main-folder/sub1/file2: Привет , говорит Git, там уже есть главная папка / sub1, я могу просто создатьтам новый файл file2.

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

Если выТеперь вы переключаетесь с , чтобы зафиксировал другой коммит, Git удалит все файлы, созданные для этого коммита, и заменит их файлами для другого, другого коммита. Если он удаляет все файлы из main-folder/sub1, он также удаляет каталог main-folder/sub1. Если в main-folder он все удаляет, он тоже удаляется. Затем идет извлечение всех файлов из коммита, который вы хотите сейчас, создание любых каталогов / папок, как требуется.

Фактически, Git чередует всю эту работу, создавая и удаляя и оптимизируя: если вы переключаетесь с коммита a123456... на коммит b789abc..., и 99% файлов в двух коммитах одинаковы , ну, в конце концов, нет необходимости копаться с ними в рабочем дереве, не так ли? И с этой конкретной формой git checkout Git добавляет проверку безопасности перед переключением коммитов: Для каждого файла, который я должен удалить или заменить, является ли файл в рабочем дереве "чистым"? Если Файл «чистый», его можно удалить или заменить. Если он «грязный» - если вы изменили его с тех пор, как Git извлек его, и вы можете сохранить свои изменения, чтобы переключение могло сработать - Git предупредит вас об этом и по умолчанию откажется переключать коммиты.

Указатель / промежуточная зона

В этом процессе есть одна огромная морщинка. Прочитав вышесказанное, вы подумали бы: Хорошо, у нас есть коммиты с сублимированными файлами и рабочим деревом с обычными файлами. Но есть третий объект, который Git помещает между эти двое. Это индекс / область подготовки.

Как и сами коммиты, индекс в основном невидим. На самом деле это просто обычный файл, в большинстве случаев .git/index - со временем это усложняется, но начинается как простой файл. В этом файле находится, по сути, копия извлеченного вами коммита - все лиофилизированные файлы, использующие только хеш-идентификатор (например, хеш-идентификаторы коммитов) для их идентификации. Однако, в отличие от фактически замороженных файлов в коммитах, копии в индексе можно изменить. 2

Это то, что делает git add: он замораживает файл и вставляет эту версию в индекс. Если файл не был в индексе раньше, ну, теперь это так. Если это было в индексе ранее, это исключает предыдущую версию. В любом случае новый высушенный замораживанием файл готов к фиксации. Когда вы запускаете git commit, Git просто упаковывает все готовые к использованию файлы из индекса в новый коммит. Именно поэтому почему git commit так быстро: на самом деле осталось совсем немного работы.

Файлы в индексе вообще не хранятся в папках. Есть только один гигантский список: файл path/to/file1 содержит эти лиофилизированные файлы, файл path/to/file2 содержит эти другие лиофилизированные материалы и так далее. Но так или иначе, наличие файла в индекса - вместе с лиофилизированным содержимым, готовым к фиксации, - это то, что делает регидратированный файл в рабочем дереве отслеживаемым . отслеживаемый файл - это файл, который находится в индексе, поэтому неотслеживаемый файл - это просто любой файл, который находится в рабочем дереве, но отсутствует в индексе. Так как git commit архивирует то, что находится в index , а не то, что находится в рабочем дереве, только 1181 * отслеженные файлы фиксируются.


2 Сложность в том, что помещение нового файла в индекс фактически останавливает его сушку и сохраняет его в репозитории , создавая новый идентификатор хэша, если новый содержимое действительно новое или разделяет какой-либо существующий хэш-идентификатор, если сублимированное содержимое совпадает с любым существующим файлом Теперь, когда предположительно новый файл уменьшен до хеш-идентификатора, он помещается в тот же слот в индексе, который занимал старый файл!


С этим из пути ответ теперь прост

МакКаждый новый коммит, который в этом коммите хранит только определенных файлов, просто настройте так, чтобы в вашем index были только эти файлы.Для этого удалите все полностью нежелательные файлы из вашего индекса, что также удалит копии рабочего дерева:

git rm ...

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

git mv main-folder/sub1 sub1

, который создаст (переименовав в этомcase) папку sub1 в вашем рабочем дереве, если необходимо, затем переименуйте все отслеживаемые файлы в индексе - помните, что git mv должен работать как с индексом, так и с рабочим деревом -из их main-folder/sub1/file1 и т.д. путей, чтобы иметь sub1/file1 и т.д. пути.Команда git mv, как и команда git rm, затем перетаскивает файлы рабочего дерева вместе с ней.

(Удобно, а иногда и нет, когда git mv переименовывает папку на месте, чтотакже переименовывает любые неотслеживаемые файлы внутри него. Так как остальная часть Git на самом деле не заинтересована в неотслеживаемых файлах, более поздняя git checkout не будет перемещать их назад!)

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

Обратите внимание, что когда вы переключаетесь между этими коммитами, с этими * 1237При вводе имен *, для любого коммита, который имеет имена типов main-folder/sub1/file1, Git, возможно, придется сильно сжать ваше рабочее дерево, сначала удалив все имена sub1/file1, а затем создав новые, пустые main-folder и main-folder/sub1каталоги для хранения (в конце концов, таких же!) файлов, которые были в sub1/file1 и так далее.Когда и если Git может быть достаточно умным, чтобы понять, что он может просто переименовать эти файлы в рабочем дереве, Git может сделать это, но простой тупой способ, с которого Git обычно начинает работать, это простоудалить и воссоздать их.Это будет отображаться в отметках времени файла на уровне ОС: если Git удаляет файл и создает его заново, он получает отметку «сейчас» в качестве временной отметки файла рабочего дерева на диске.


3 Внутри коммитов - но не в индексе - Git возвращается к древовидной схеме именования.Так что если sub1 на верхнем уровне этого нового коммита на 100% идентичен sub1, который был в main-folder/sub1 некоторого другого коммита, Git фактически поделится базовым деревом объекта для sub1 поддерево корневого дерева нового коммита.Разумеется, корневое дерево будет другим, поскольку оно будет называть sub1 одним из своих поддеревьев, а не называть main-folder одним из своих поддеревьев.Но все это просто детали реализации: ничего из этого не отображается в индексе и рабочем дереве.

0 голосов
/ 14 мая 2019

структура папок специфична для каждой ветви.Поэтому сначала вам нужно проверить новую ветку

git checkout branch1, а затем переместить подпапки 1 и 2 из основной папки, удалить git commit

, если у вас возникнут дополнительные вопросы о том, как работает git.Есть много хороших учебников = возможно, начиная с https://girliemac.com/blog/2017/12/26/git-purr/ GIT с котятами

...