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

Другие полезные команды

  • откатить рабочий каталог к ревизии № rev. — (допустим четырехзначный формат); — откатить конкретный файл
  • посмотреть старую версию файла (в т.ч. удалённого):
  • убрать файл из-под контроля git, оставив его при этом на диске: ; очень важна при этом опция — без неё команда удалит файл и с диска
  • — начать с пустого сообщения для коммита в редакторе, без
  • — просмотр списка неотслеживаемых файлов; — исключить из списка игнорируемые, — не разворачивать содержимое неотслеживаемых каталогов (в список тогда попадут также пустые каталоги — они никогда не отслеживаются)
  • — показывать полный список игнорируемых файлов

Частые вопросы

Что отличает git fetch и git pull?

Команда git fetch и команда git pull отличаются друг от друга по работе. Git fetch извлекает изменения, в то время как git pull объединяет их после извлечения. Таким образом, в некотором смысле git fetch является частью git pull, поскольку он сначала извлекает изменения, а затем выполняет git merge.

Могу ли я отменить изменения, внесенные git merge?

Да, в Git слияние изменений может повернуть вспять с помощью следующих действий. Определите коммит, к которому вы хотите вернуться с помощью команды git reflog. Выполните жесткий сброс вместе с хэшем фиксации с помощью git reset –hard <hash>.

Git push

Команда в ходе выполнения переносит все изменения, внесенные юзером, в удаленный репозиторий (например, такой как GitHub):

Git push 'remote_name' 'branch_name'

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

Вынужденная команда push при корректировке коммитов:

# make changes to a repo and git add

              git commit --amend

# update the existing commit message

       git push --force origin main

Команда применяется для обновления прошлого коммита. Только после этого измененный коммит вынужденно выпускается с помощью команды .

1 ответ

По словам Линуса ( https://mirrors.edge.kernel.org/pub/software/scm/git/docs/howto/revert-a-faulty-merge.txt):

Итак, это объясняет, почему не эффективная стратегия, но что мы можем сделать? Давайте рассмотрим следующее:

  • ABC — это функция / ветка релиза
  • M — плохое слияние, где изменения от AB были отброшены, но C был сохранен
  • DE позже работает над
  • остальные несвязанные изменения в основной ветке

Пока М существует на , предполагается, что история ABC была интегрирована, хотя дельты AB отсутствуют. Чтобы восстановить их без изменения истории нам нужно воссоздать дельты в альтернативной истории (т.е. новые идентификаторы коммитов).

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

Следующим вариантом является использование воссоздать новый ветка, из которой можно объединить потерянные изменения.

Что создает следующее:

Первоначальное слияние M, скорее всего, стало проблемой только из-за конфликтов слияния. Одна из проблем этого подхода заключается в том, что вы не только должны правильно разрешить исходный конфликт в ABC, но и теперь у вас есть новый возможный источник конфликта в DE и TU, с которым нужно бороться. В чрезвычайной ситуации это может быть волосатым, чтобы понять, что происходит.

Предпочтительное решение:

Более простая стратегия, использующая инструменты, с которыми вы, вероятно, знакомы, состоит в том, чтобы правильно воссоздать слияние, используя совершить (M2). Это создает новый идентификатор фиксации (новая история), и, таким образом, дельты из AB могут быть успешно интегрированы обратно в основную линию. Этот метод также исключает возможные источники конфликта слияния, позволяя сначала исправить ошибку, а затем заняться изменениями в восходящем направлении.

Метод:

Отделение от перед неудачным слиянием (M)

Теперь у вас есть чистый лист, с которого вы можете выполнить исправленное слияние

Флаг сквоша сведет эти изменения в один коммит, но, что более важно, он сгенерирует новый идентификатор коммита. Скорее всего, в этот момент вам нужно будет разрешить конфликты, однако M2 теперь представляет все данные, которые M должен был изначально содержать

Теперь вы можете объединить это с dev, как обычно

Скорее всего, в этот момент вам нужно будет разрешить конфликты, однако M2 теперь представляет все данные, которые M должен был изначально содержать. Теперь вы можете объединить это с dev, как обычно

Опять же, могут возникнуть конфликты слияния, но после этого момента (M3) вы восстановили свои недостающие данные. Теперь вы можете действовать как обычно, например, вы можете объединить DE из в или любые другие ваши обычные операции. Это также означает, что другие члены команды не должны сбрасывать свои локальные ветвь, как он будет восстанавливаться, когда они в следующий раз выполнить ,

1

2018-10-25 10:57

Немного о работе с github.com

При первой отправке изменений в пустой, только что созданный, репозиторий нужно явно установить (обычно — продублировать) название будущей ветки. Делается это с помощью ключа /:

или, в общем случае

Делать это можно только при наличии коммитов в локальной ветке. При пустой ветке команда не сработает.

Personal access token

upd 19.02.2021: пароль от аккаунта в командной строке по-прежнему работает нормально, по крайней мере, если указывать адрес репозитория на github через

С 1 июля 2020 года GitHub требует использовать некие personal access token (PAT) вместо простых паролей к учетной записи на github.

Вот несколько материалов, которые проливают на них свет:

Как создавать access token: https://help.github.com/articles/creating-an-access-token-for-command-line-use/

Git merge

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

Конфликт в слиянии

Бывают случаи, когда находит конфликт в слиянии и к файлам присоединяются индикаторы: , и :

<here is some content not affected by the conflict

<<<<<<< main

this is conflicted text from main

=======

this is conflicted text from feature branch

>>>>>>> feature branch;

По завершению слияния, выполните команду : таким образом вы проинформируете, что причина конфликта разрешена

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

Создание новой ветви в командной строке

Программа Git в командной строке предлагает максимальную мощность и гибкость, но есть чему поучиться. Если вам удобно копаться в man-страницах и активно использовать Git, это отличный вариант.

Используйте команду git branch <branchname>, чтобы создать новую ветку с заданным именем:

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

Вы можете перечислить все ветки и подтвердить, что новая была создана, с помощью git branch без каких-либо аргументов:

Вы можете увидеть дополнительную информацию, в том числе, какую ветвь отслеживает другая, используя флаг -vv :

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

Если вы попытаетесь создать ветку с уже существующим именем, вы получите сообщение об ошибке, например:

Команда git branch создает новую ветку, указывающую на тот же коммит, над которым вы сейчас работаете. Однако ваша рабочая копия по-прежнему будет указывать на основную ветку. Чтобы переключиться на новую ветку, которую вы только что создали, используйте git checkout :

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

Эта команда означает «создать новую ветку под названием« dev »и немедленно переключиться на нее». Это эквивалент:

Фактически, вы даже можете использовать git checkout для создания ветки из любой другой, а не только из той, которая в данный момент проверена. Например, чтобы создать новую ветку с именем another , из ветки с именем dev :

Reflog

Все делают ошибки, и это совершенно нормально! Иногда может показаться, что вы испортили свой репозиторий Git настолько сильно, что просто хотите полностью его удалить.

— очень полезная команда для отображения журнала всех выполненных действий! Это включает в себя слияния, перезагрузки, возвраты: в основном, любые изменения в вашей ветке.

Если вы допустили ошибку, вы можете легко отменить ее, сбросив HEAD на основе информации, которую нам предоставляет reflog.

Скажем, мы на самом деле не хотели мержить origin ветку. Когда мы выполняем команду , мы видим, что состояние репозитория до мержа- . Давайте выполним , чтобы указать HEAD туда, где он был.

Предпочтительное решение:

Более простая стратегия, использующая инструменты, с которыми вы, вероятно, знакомы, состоит в том, чтобы правильно воссоздать слияние, используя совершить (M2). Это создает новый идентификатор фиксации (новая история), и, таким образом, дельты из AB могут быть успешно интегрированы обратно в основную линию. Этот метод также исключает возможные источники конфликта слияния, позволяя сначала исправить ошибку, а затем заняться изменениями в восходящем направлении.

Метод:

Отделение от перед неудачным слиянием (M)

Теперь у вас есть чистый лист, с которого вы можете выполнить исправленное слияние

Флаг сквоша сведет эти изменения в один коммит, но, что более важно, он сгенерирует новый идентификатор коммита. Скорее всего, в этот момент вам нужно будет разрешить конфликты, однако M2 теперь представляет все данные, которые M должен был изначально содержать

Теперь вы можете объединить это с dev, как обычно

Скорее всего, в этот момент вам нужно будет разрешить конфликты, однако M2 теперь представляет все данные, которые M должен был изначально содержать. Теперь вы можете объединить это с dev, как обычно

Опять же, могут возникнуть конфликты слияния, но после этого момента (M3) вы восстановили свои недостающие данные. Теперь вы можете действовать как обычно, например, вы можете объединить DE из в или любые другие ваши обычные операции. Это также означает, что другие члены команды не должны сбрасывать свои локальные ветвь, как он будет восстанавливаться, когда они в следующий раз выполнить ,

Просмотр истории коммитов

Не все коммиты будете делать вы, какие-то будут делать ваши коллеги по команде, поэтому вам может понадобиться изучить историю коммитов. Одним из основных и наиболее мощных инструментов для этого является команда .

Помимо автора и даты, у каждого комита есть идентификатор, который называется hash. Пример: 2934ee19f4d4ca37ff9bea9dc8208ef5362d789e. Необязательно использовать такую длинную запись, git поймет и по первым 5 символам, какой hash вам нужен.

Команда имеет очень большое количество опций для поиска коммитов по разным критериям.

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

12 ответов

Лучший ответ

Запуск выполняет следующие задачи по порядку:

Шаг слияния объединяет ветки, которые были настроены для слияния в вашей конфигурации. Вы хотите отменить этап слияния , но, вероятно, не выборку (не имеет большого смысла и в этом нет необходимости).

Чтобы отменить слияние , используйте для сброса локального репозитория в предыдущее состояние; используйте git-reflog, чтобы найти SHA- 1 из предыдущего состояния, а затем сбросить на него.

Предупреждение

Команды, перечисленные в этом разделе, удаляют все незафиксированные изменения, что может привести к потере работы:

В качестве альтернативы можно выполнить сброс на определенный момент времени, например:

1679

Dave Jarvis
20 Сен 2019 в 19:51

То же, что и ответ jkp, но вот полная команда:

Где a0d3fe6 находится путем выполнения

И глядя на точку, в которой вы хотите отменить.

402

Jeffrey Sun
22 Июл 2014 в 00:39

Более современный способ отменить слияние:

И немного более старый способ:

Старый способ, описанный в предыдущих ответах (предупреждение: все ваши локальные изменения будут отменены):

Но на самом деле стоит отметить, что эквивалентен только при наличии . Это можно прочитать в справке git для команды слияния.

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

148

Martin G
20 Май 2015 в 09:17

Оно работает первое использование:

Найдите свой SHA предыдущего состояния и создайте (пример HEAD @ {1})

72

Ezequiel García
8 Мар 2016 в 17:00

Если у вас есть gitk (попробуйте запустить «gitk —all из командной строки git»), это просто. Просто запустите его, выберите фиксацию, к которой вы хотите выполнить откат (щелкните правой кнопкой мыши), и выберите «Сбросить главную ветку сюда». Если у вас нет незавершенных изменений, выберите «жесткий» вариант.

42

Samuel Carrijo
3 Авг 2009 в 16:49

Предположим, что был последним идентификатором фиксации перед выполнением . Что вам нужно, чтобы отменить последнее нажатие, так это

Бонус :

Говоря о вытягивании, я хотел бы поделиться интересным трюком,

Эта команда выше — самая полезная команда в моей жизни с git, которая сэкономила много времени.

Прежде чем отправлять новую фиксацию на сервер, попробуйте эту команду, и она автоматически синхронизирует последние изменения сервера (с помощью fetch + merge) и поместит вашу фиксацию наверху в журнале git. Не нужно беспокоиться о ручном извлечении / слиянии.

Подробности можно найти на странице: http://gitolite.com/git-pull—rebase

42

Community
20 Июн 2020 в 09:12

Это самый простой способ отменить изменения.

Сделайте резервную копию измененных файлов, поскольку при этом будут удалены вновь созданные файлы и папки .

Где — ваш {идентификатор фиксации}

20

Manish Goswami
5 Дек 2019 в 07:25

Ты можешь сделать

Так как «pull» или «merge» устанавливают ORIG_HEAD как текущее состояние перед выполнением этих действий.

18

Orlando
19 Авг 2015 в 17:02

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

7

Davide
24 Сен 2018 в 17:35

git pull выполните операцию ниже.

Чтобы отменить вытягивание, выполните любую операцию:

Улучшение:

В следующий раз используйте вместо .. его сервер синхронизации измените, выполнив (выборка и слияние).

5

GolamMazid Sajib
5 Апр 2020 в 13:38

Попробуй бежать

3

henrique_ms
27 Авг 2020 в 18:06

Самый быстрый способ решить эту проблему —

3

Azeez Bello
13 Мар 2021 в 16:33

Merge

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

Один из способов получить изменения из одной ветки в другую — выполнить ! Есть два типа менж команд, которые может выполнять Git: fast-forward или no-fast-forward 

Fast-forward ()

Fast-forward merge когда текущая ветка не имеет дополнительных коммитов по сравнению с веткой, которую мы мержим. Git у нас ленив и сначала попытается выполнить самый простой вариант: Fast-forward! Этот тип менжа не создает новый коммит, а скорее объединяет коммит(ы) в ветку, которую мы объединяем прямо в текущей ветке

Отлично! Теперь у нас есть все изменения, которые были сделаны в ветке , в ветке . Итак, что же такое  no-fast-forward?

No-fast-foward ()

Хорошо, если ваша текущая ветка не имеет каких-либо дополнительных коммитов по сравнению с веткой, которую вы хотите смержить, но, к сожалению, это случается редко! Если мы зафиксировали изменения в текущей ветке, которых нет в ветке, которую мы хотим объединить, git выполнит объединение без fast-forward merge. При слиянии без fast-forward Git создает новый коммит мержа в активную ветку. Родительский коммит указывает на активную ветку и ветку, которую мы хотим объединить!

Merge конфликты

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

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

Если мы хотим смержить  в , это приведет к конфликту: хотите, чтобы заголовок был Hello! или hey!?

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

Как использовать команду Git Merge?

Чтобы объединить изменения, полученные в предыдущем разделе, выполните следующую команду:

git merge

Если вы видите такой же результат, значит, вы успешно объединили изменения в своем локальном репозитории. На приведенном выше изображении третья строка показывает написанное Fast-forward (перемотка вперед). Это происходит потому, что это fast-forward merge (быстрое слияние), выполняемое git. Давайте посмотрим, что это такое.

Fast-Forward Merge

Fast-Forward Merge (быстрое слияние) в Git означает, что существует линейный путь от ветви, который отклоняется от ветви, к которой вы сливаетесь. Линейный путь означает, что не было никаких коммитов к главной ветви с тех пор, как ветвь объекта перешла в точку слияния.

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

Reset

Может случиться так, что мы допустили изменения, которые мы не хотели заливать. Может быть, это коммит еще в работе или коммит, в котором есть ошибки! В этом случае мы можем выполнить .

 избавляет от всех текущих промежуточных файлов и дает нам контроль над тем, куда должен указывать HEAD.

Soft reset

Soft reset перемещает HEAD к указанному коммиту (или индексу коммита по сравнению с HEAD), не избавляясь от изменений, которые были внесены в коммиты позже.

Допустим, мы не хотим сохранять коммит , в который был добавлен файл , и мы также не хотим сохранять коммит , в который был добавлен файл . Однако мы хотим сохранить недавно добавленные файлы и  Идеальный кейс для sort reset.

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

Hard reset

Иногда мы не хотим сохранять изменения, внесенные некоторыми коммитами. В отличие от soft reset, нам не нужно больше иметь к ним доступ. Git должен просто сбросить свое состояние обратно туда, где он был в указанном коммите: это даже включает изменения в вашей working directory и stage файлах!

Git отменил изменения, которые были внесены в 9e78i и 035cc, и сбросил свое состояние до того, где он был при коммите ec5be.

Отмена изменений

Вернуть файл к состоянию последнего коммита (аналог ) можно командой .
Уточнение: файл будет возвращен к зафиксированному состоянию, если после коммита была явно дана команда . То есть, откатываются изменения, сделанные после или .
Если файл был удален, то нужно указать версию; например .

Так можно откатить и всю папку (в т.ч. рабочий каталог): .

Для отмены изменений на уровне рабочей копии служит команда . Она «отматывает» историю изменений назад до указанного момента (в том числе отменяет коммиты), не трогая физические файлы:

git reset файл

С ключом переписываются и файлы.

  • — отменить последний коммит
  • — отменить два последних коммита

Отменять коммиты можно, только если они не опубликованы в общий репозиторий (не было git push).

Отменить добавление нового файла в индекс можно командой .

Rebase

Мы только что увидели, как можно применить изменения из одной ветки в другую, выполнив . Другой способ добавить изменения из одной ветки в другую — выполнить .

Git rebase копирует коммиты из текущей ветки и помещает эти скопированные коммиты поверх указанной ветки.

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

Большая разница по сравнению с мержем заключается в том, что Git не будет пытаться выяснить, какие файлы сохранить и не сохранить. В ветке, которую мы обновляем, всегда есть последние изменения, которые мы хотим сохранить! Таким образом, вы не столкнетесь ни с какими мерж конфликтами и у вас будет хорошая линейная история.

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

Rebase отлично подходит, когда вы работаете над feature branch, а master ветка была обновлена. Вы можете получить все обновления в своей ветке, которые предотвратят будущие merge конфликты 

Interactive Rebase

Перед rebas’ом коммитов мы можем их изменить! Мы можем сделать это с помощью Interactive Rebase. Interactive Rebase также может быть полезен для ветки, над которой вы сейчас работаете, и хотите изменить некоторые коммиты.

Есть 6 действий, которые мы можем выполнить над коммитами, которые мы rebas’им:

  • : Изменить коммит меседж
  • : Изменить коммит
  • : Объеденить коммит в предыдущий коммит
  • : Объединить коммит с предыдущим коммитом, не сохраняя commit’s log message
  • : Запустить команду для каждого коммита, который мы хотим rebase
  • : Удалить коммит

Таким образом, мы можем иметь полный контроль над нашими коммитами. Если мы хотим удалить коммит, мы можем просто drop’нуть его.

Или, если мы хотим объединить несколько коммитов вместе, чтобы получить более чистую историю, нет проблем!

Interactive rebasing дает вам большой контроль над коммитами, которые вы пытаетесь rebase’нуть, даже в текущей активной ветке.

Общее

Git — система контроля версий (файлов). Что-то вроде возможности сохраняться в компьютерных играх (в Git эквивалент игрового сохранения — коммит)

Важно: добавление файлов к «сохранению» двухступенчатое: сначала добавляем файл в индекс (), потом «сохраняем» ()

Любой файл в директории существующего репозитория может находиться или не находиться под версионным контролем (отслеживаемые и неотслеживаемые).

Отслеживаемые файлы могут быть в 3-х состояниях: неизменённые, изменённые, проиндексированные (готовые к коммиту).

Ключ к пониманию

Ключ к пониманию концепции git — знание о «трех деревьях»:

  • Рабочая директория — файловая система проекта (те файлы, с которыми вы работаете).
  • Индекс — список отслеживаемых git-ом файлов и директорий, промежуточное хранилище изменений (редактирование, удаление отслеживаемых файлов).
  • Директория — все данные контроля версий этого проекта (вся история разработки: коммиты, ветки, теги и пр.).

Коммит — «сохранение» (хранит набор изменений, сделанный в рабочей директории с момента предыдущего коммита). Коммит неизменен, его нельзя отредактировать.

У всех коммитов (кроме самого первого) есть один или более родительских коммитов, поскольку коммиты хранят изменения от предыдущих состояний.

Простейший цикл работ

  • Редактирование, добавление, удаление файлов (собственно, работа).
  • Индексация/добавление файлов в индекс (указание для git какие изменения нужно будет закоммитить).
  • Коммит (фиксация изменений).
  • Возврат к шагу 1 или отход ко сну.

Указатели

  • — указатель на текущий коммит или на текущую ветку (то есть, в любом случае, на коммит). Указывает на родителя коммита, который будет создан следующим.
  • — указатель на коммит, с которого вы только что переместили (командой , например).
  • Ветка (, etc.) — указатель на коммит. При добавлении коммита, указатель ветки перемещается с родительского коммита на новый.
  • Теги — простые указатели на коммиты. Не перемещаются.

Перед началом работы нужно выполнить некоторые настройки:

Если вы в Windows:

Длинный вывод в консоли: Vim

Если нужно что-то написать, нажмите i — это переход в режим вставки текста. Если нужно сохранить изменения, перейдите в командный режим и наберите :w.

# Нажатия кнопок
ESC     — переход в командный режим
i       — переход в режим редактирования текста
ZQ (зажат Shift, поочередное нажатие) — выход без сохранения
ZZ (зажат Shift, поочередное нажатие) — сохранить и выйти
```bash
# Нажатия кнопок
ESC     — переход в командный режим
i       — переход в режим редактирования текста
ZQ (зажат Shift, поочередное нажатие) — выход без сохранения
ZZ (зажат Shift, поочередное нажатие) — сохранить и выйти

# Ввод в командном режиме
:q!             — выйти без сохранения
:wq             — сохранить файл и выйти
:w filename.txt — сохранить файл как filename.txt
Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Все про сервера
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: