Я использую Perforce несколько лет. Я хотел бы переключиться на использование git для моего личного кода, но все учебные пособия по git, которые я видел, либо предполагают, что у вас есть полный исходный контроль n00b (что делает их невероятно утомительными), либо что вы привыкли к svn (а я не такой).
Я знаю p4, и я также понимаю идею распределенной системы управления исходным кодом (так что мне не нужна реклама, спасибо). Что мне нужно, так это таблица перевода из команды p4 в эквивалентные команды git, а также команды «не могу жить без», у которых нет эквивалента p4.
Поскольку я подозреваю, что каждый пользователь p4 использует другое подмножество p4, вот некоторые из вещей, которые я регулярно делаю в p4, которые я хотел бы делать в git, которые не сразу очевидны из документов, которые я просмотрел. :
- создать несколько ожидающих списков изменений в одном клиенте. (
p4 change
) - редактировать ожидающий список изменений. (также
p4 change
) - просмотреть список всех ожидающих меня списков изменений (
p4 changes -s pending
) - список всех измененных файлов в моем клиенте (
p4 opened
) или в списке ожидающих изменений (p4 describe
) - увидеть разницу в ожидающем списке изменений (я использую для этого сценарий-оболочку, который использует
p4 diff
иp4 describe
) - для данного файла посмотрите, какие отправленные списки изменений повлияли на какие строки (
p4 annotate
) - для данного файла см. список описаний списков изменений, которые повлияли на файл (
p4 log
) - отправить ожидающий список изменений (
p4 submit -c
) - прервать отложенный список изменений (
p4 revert
)
Многие из них вращаются вокруг «списков изменений». "список изменений" - это терминология p4. Что такое термин, эквивалентный git?
Похоже, что ветки могут быть тем, что пользователи git используют вместо того, что p4 вызывает списки изменений. Немного сбивает с толку, поскольку в p4 также есть что-то, называемое ветвью, хотя они, похоже, лишь смутно связаны между собой. (Хотя мне всегда казалось, что концепция ветки в p4 довольно странная, она опять же отличается от классической концепции RCS ветки.)
В любом случае ... Я не уверен, как выполнить то, что я обычно делаю в списках изменений p4 с ветками git. В p4 я могу сделать что-то вроде этого:
$ p4 edit a.txt
$ p4 change a.txt
Change 12345 created.
На данный момент у меня есть список изменений, содержащий a.txt. Я могу отредактировать описание и продолжить работу, не отправляя список изменений. Кроме того, если окажется, что мне нужно внести некоторые изменения в некоторые другие файлы, например, исправить ошибку в каком-то другом слое кода, я могу сделать это в том же клиенте:
$ p4 edit z.txt
$ p4 change z.txt
Change 12346 created.
Теперь у меня есть два отдельных списка изменений в одном клиенте. Я могу работать над ними одновременно, и мне не нужно ничего делать, чтобы «переключаться между ними». Когда приходит время коммитить, я могу отправить их отдельно:
$ p4 submit -c 12346 # this will submit the changes to z.txt
$ p4 submit -c 12345 # this will submit the changes to a.txt
Я не могу понять, как воспроизвести это в git. Судя по моим экспериментам, он не git add
связан с текущей веткой. Насколько я могу судить, когда я git commit
собираюсь зафиксировать все файлы, которые я git add
создал, независимо от того, в какой ветке я был в то время:
$ git init
Initialized empty Git repository in /home/laurence/git-playground/.git/
$ ls
a.txt w.txt z.txt
$ git add -A .
$ git commit
Initial commit.
3 files changed, 3 insertions(+), 0 deletions(-)
create mode 100644 a.txt
create mode 100644 w.txt
create mode 100644 z.txt
$ vi a.txt z.txt
2 files to edit
$ git status
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: a.txt
# modified: z.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git branch aardvark
$ git checkout aardvark
M a.txt
M z.txt
Switched to branch 'aardvark'
$ git add a.txt
$ git checkout master
M a.txt
M z.txt
Switched to branch 'master'
$ git branch zebra
$ git checkout zebra
M a.txt
M z.txt
Switched to branch 'zebra'
$ git add z.txt
$ git status
# On branch zebra
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: a.txt
# modified: z.txt
#
$ git checkout aardvark
M a.txt
M z.txt
Switched to branch 'aardvark'
$ git status
# On branch aardvark
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: a.txt
# modified: z.txt
В этом примере ветви трубкозуба и зебры, кажется, содержат точно такой же набор изменений, и на основе его результатов git status
кажется, что выполнение фиксации в любом из них будет иметь одинаковый эффект. Я делаю что-то неправильно?
Ответы:
Я не слишком много использовал принудительно, поэтому это может быть не совсем перевод 1: 1. С другой стороны, распределенные системы управления исходным кодом, такие как git и mercurial, в любом случае имеют другой рабочий процесс, поэтому на самом деле нет (и не должно быть) перевода 1: 1. Во всяком случае, вот идет:
Создайте несколько ожидающих списков изменений -> Вместо этого используйте ветки. В git ветки легкие и быстрые, на их создание уходит меньше секунды, а на слияние обычно меньше двух секунд. Не бойтесь частого ветвления и перестановки.
Или сделайте все в одной строке:
См. Список всех ожидающих списков изменений -> Поскольку эквивалентом нескольких ожидающих списков изменений является несколько веток, просто просмотрите ветки:
Если вы хотите также просмотреть удаленные ветки:
Считается хорошей практикой немедленно удалить ветку после успешного слияния, поэтому вам не нужно отслеживать, какие ветки ожидают слияния, а какие уже слиты.
Список всех измененных файлов -> Для одного ожидающего «списка изменений» в определенной ветке git имеет понятие индекса или кеша. Чтобы зафиксировать изменение, вы должны сначала добавить файлы в этот индекс. Это позволяет вам вручную выбрать, какая группа файлов представляет собой одно изменение, или игнорировать нерелевантные файлы. Чтобы узнать, какие файлы добавлены или нет в этот индекс, просто выполните:
См. Различие ожидающего списка изменений -> Это состоит из двух частей. Сначала, чтобы увидеть разницу между рабочим каталогом и индексом:
Но если вы хотите знать разницу между тем, что вы вводите сейчас, и последней фиксацией, тогда вы действительно запрашиваете разницу между рабочим каталогом + index и HEAD:
Для данного файла посмотрите, какие отправленные списки изменений повлияли на какие строки -> Это просто:
или даже лучше, если вы находитесь в оконной среде:
Git gui занимает больше времени для синтаксического анализа файла (он был написан на tcl вместо C), но у него есть множество полезных функций, включая возможность «путешествовать во времени» назад в прошлое, щелкнув идентификатор фиксации. Я только хотел бы, чтобы они реализовали функцию "путешествия во времени" в будущее, чтобы я мог узнать, как в конечном итоге будет решена данная ошибка ;-)
Для данного файла просмотрите список описаний списков изменений, которые повлияли на этот файл -> также просто:
Но git log - гораздо более мощный инструмент, чем это. Фактически, большинство моих личных сценариев извлекаются из журнала git для чтения репозитория. Прочтите страницу руководства.
Отправить ожидающий список изменений -> Также просто:
См. Мой ответ на предыдущий вопрос, чтобы увидеть мой типичный рабочий процесс с git: изучение Git. Нужно знать, на правильном ли я пути
Если вы будете следовать описанному мною рабочему процессу, то вы обнаружите, что такие инструменты, как gitk, будут гораздо более ценными, поскольку он позволяет четко видеть группы изменений.
Дополнительный ответ:
Git очень гибкий, и есть несколько способов делать то, что вы описываете. Следует помнить, что всегда нужно начинать новую ветку для каждой функции, над которой вы работаете. Это означает, что основная ветка не затрагивается, поэтому вы всегда можете вернуться к ней, чтобы исправить ошибки. Работу в git почти всегда следует начинать с:
Теперь вы можете редактировать файл a.txt. Чтобы одновременно работать над другой функцией, выполните:
Теперь вы можете редактировать файл z.txt. Чтобы вернуться к a.txt:
Но подождите, есть изменения в new-feature-z, и git не позволит вам переключать ветки. На данный момент у вас есть два варианта. Первый самый простой, зафиксируйте все изменения в текущей ветке:
Это то, что я рекомендую. Но если вы действительно не готовы зафиксировать код, вы можете временно спрятать его:
Теперь вы можете переключиться на ветку new-feature-a. Чтобы вернуться к коду, над которым вы работали, просто откройте тайник:
Когда все будет готово, объедините все изменения в master:
Поскольку слияние происходит так быстро и легко (легко, потому что конфликты настолько редки, а разрешение конфликтов, если оно действительно происходит, не слишком сложно), мы используем ветки в git для всего.
Вот еще один пример общего использования веток в git, который вы не видите в других инструментах управления версиями (кроме, возможно, Mercurial):
Необходимо постоянно изменять файлы конфигурации, чтобы они отражали среду разработки? Затем используйте ветку:
Теперь отредактируйте свои файлы конфигурации в любимом редакторе, а затем зафиксируйте изменения:
Теперь каждая новая ветка может начинаться с ветки dev-config вместо master:
Как только вы закончите, удалите правки в dev-config из new-feature-branch с помощью интерактивной перебазировки:
Удалите ненужные коммиты и сохраните. Теперь у вас есть чистая ветка без пользовательских правок конфигурации. Время слиться с мастером:
Следует отметить, что удаление правок
git rebase -i
работает даже тогда, когда все изменения происходят в одном файле. Git запоминает изменения, а не содержимое файла *.* примечание: на самом деле технически не совсем верно, но как пользователь это чувствует
Дополнительный ответ:
Итак, из ваших комментариев, похоже, вы хотите, чтобы две ветки существовали одновременно, чтобы вы могли проверить, как работает комбинированный код. Что ж, это хороший способ продемонстрировать мощность и гибкость ветвей.
Во-первых, несколько слов о влиянии дешевых ветвлений и изменяемой истории на ваш рабочий процесс. Когда я использовал CVS и SVN, я всегда немного сопротивлялся фиксации. Это потому, что коммит нестабильного кода неизбежно испортит рабочий код других людей. Но с git я избавился от этого страха. Это потому, что в git другие люди не получат мои изменения, пока я не объединю их в master. Итак, теперь я фиксирую код каждые 5 строк, которые пишу. Чтобы совершить что-то, вам не нужно совершенное предвидение. Вам просто нужно изменить свое мышление: commit-to-branch == add-to-changeset, merge-to-master == commit-changeset.
Итак, вернемся к примерам. Вот как бы я это сделал. Скажем, у вас есть ветка,
new-feature-z
и вы хотите ее протестироватьnew-feature-a
. Я бы просто создал новую ветку для проверки:Теперь можно протестировать. Если вам нужно что-то изменить, чтобы функция feature-z работала с feature-a, сделайте это. В таком случае вы можете объединить изменения в соответствующую ветку. Используйте
git rebase -i
для удаления несущественных изменений из слияния.В качестве альтернативы вы также можете использовать git rebase, чтобы временно изменить базу new-feature-z, чтобы указать на new-feature-a:
Теперь история веток изменена так, что new-feature-z будет основываться на new-feature-a, а не на master. Теперь можно протестировать. Любые изменения, внесенные в эту ветку, будут принадлежать ветке new-feature-z. Если вам нужно изменить new-feature-a, просто вернитесь к нему и переустановите, чтобы получить новые изменения:
Когда вы закончите, просто вернитесь к master, чтобы удалить изменения из new-feature-a:
Не бойтесь начинать новую ветку. Не бойтесь открывать одноразовую ветку. Не бойтесь выбрасывать ветки. И поскольку merge == submit и commit == add-to-changeset, не бойтесь часто коммитить. Помните, что коммит - это лучший инструмент для отмены действий разработчика.
Да, и еще одна вещь, в git удаленные ветки все еще существуют в вашем репозитории. Так что, если вы случайно удалили что-то, что, как вы позже понимаете, полезно, вы всегда можете вернуть это, выполнив поиск в истории. Так что не бойтесь выбрасывать ветки.
источник
У меня недостаточно опыта работы с p4, чтобы создать настоящую шпаргалку, но есть по крайней мере некоторые сходства, к которым можно вернуться. «Набор изменений» p4 - это git «commit».
Изменения в вашем локальном рабочем пространстве добавляются в «индекс» с помощью
git add
, а затем индекс фиксируется с помощьюgit commit
. Таким образом, индекс - это ваш ожидающий список изменений для всех намерений и целей.Вы смотрите на изменения с помощью
git diff
иgit status
, гдеgit diff
обычно отображаются изменения между рабочей областью и индексом, ноgit diff --cached
отображаются изменения между индексом и репозиторием (= ваш ожидающий список изменений).Для получения более подробной информации я рекомендую http://progit.org/book/ . Поскольку вы в целом разбираетесь в управлении версиями, вы, вероятно, можете просмотреть большую его часть и извлечь информацию, специфичную для git ...
источник
Я страдаю, как и вы, из-за отсутствия концепции «списка изменений», которая не совсем такая же, как ветки git.
Я бы написал небольшой скрипт, который создаст файл списка изменений со списком файлов в этом списке.
Другая команда для отправки только определенного списка изменений путем простого вызова git commit -a @ change_list_contents.txt, а затем "git commit"
Надеюсь, это поможет, Элиас
источник
В git есть более легкая альтернатива, которая может стать частью вашего рабочего процесса; используя промежуточную область git.
Я часто просто вношу изменения, а затем отправляю их в виде нескольких коммитов (например, добавляю операторы отладки, рефакторинг, фактически исправляю ошибку). Вместо того, чтобы настраивать свои списки изменений по желанию, затем вносить изменения и затем отправлять, вы можете просто внести свои изменения и выбрать способ их отправки (при желании с помощью промежуточной области git).
Вы можете зафиксировать определенные файлы из командной строки с помощью:
Или сначала явно разместить файлы:
git gui позволит вам выбирать строки или фрагменты из файлов для создания фиксации в промежуточной области. Это очень полезно, если у вас есть изменения в одном файле, которые вы хотите внести в разные коммиты. Я перешел от git к perforce, и это то, чего мне очень не хватает.
При этом рабочем процессе следует иметь в виду небольшую оговорку. Если вы вносите изменения A и B в файл, проверяете файл, затем фиксируете A, значит, вы не тестировали эту фиксацию (независимо от B).
источник
Это не отвечает конкретно на ваш вопрос, но я не знаю, знаете ли вы, что версию perforce для 2 пользователей и 5 рабочих областей можно бесплатно загрузить и использовать с веб-сайта perforce .
Таким образом, вы можете использовать perforce дома для своих личных проектов, если хотите. Единственное раздражение - это 5 рабочих пространств, которые могут немного ограничивать, но довольно невероятно, чтобы по необходимости было доступно для домашнего использования.
источник
Я достаточно широко использовал как Perforce, так и git, поэтому я вижу только один способ приблизиться к спискам изменений Perforce с помощью git.
Первое, что нужно понять, это то, что для правильной реализации этой функции в git таким образом, чтобы это не был полный клудж, например, попытка втиснуть его в ветки, потребует следующего изменения: git потребует несколько промежуточных областей для одной ветки .
Списки изменений Perforce разрешают рабочий процесс, которому просто нет эквивалента в git. Рассмотрим следующий рабочий процесс:
Если вы попытаетесь сделать это с помощью веток в git, вы получите две ветки, в одной из которых есть изменения в файле
A
, а в другой - изменения в файлеB
, но нет места, где вы можете увидеть изменения в обоих файлахA
иB
в в то же время.Ближайшее приближение я могу видеть это использовать ,
git add . -p
а затем использовать'a'
и'd'
суб-команды , чтобы выбрать или отклонить файлы целиком. Однако это не совсем одно и то же, и разница здесь проистекает из фундаментального различия в общих способах работы двух систем.Git (и subversion, но это не имеет значения для этого обсуждения) позволяют изменять файл, не сообщая об этом заранее. Вы просто меняете файл, а затем позволяете git разбираться со всем этим, когда вы фиксируете изменения. Perforce требует, чтобы вы активно извлекали файл, прежде чем изменения будут разрешены, и именно по этой причине должны существовать списки изменений. По сути, Perforce требует, чтобы вы добавили файл в индекс перед его изменением. Отсюда необходимость в нескольких списках изменений в Perforce, а также причина, по которой у git нет эквивалента. Они ему просто не нужны.
источник
В Git 2.27 (второй квартал 2020 г.) "
git p4
" изучил четыре новых хука, а также "--no-verify
" возможность их обхода (и существующий "p4-pre-submit
" крючок).См. Фиксацию 1ec4a0a , фиксацию 38ecf75 , фиксацию cd1e0dc (14 февраля 2020 г.) и фиксацию 4935c45 , фиксацию aa8b766 , фиксацию 9f59ca4 , фиксацию 6b602a2 (11 февраля 2020 г.) Бен Кин (
seraphire
) .(Объединено Junio C Hamano -
gitster
- в коммите 5f2ec21 , 22 апреля 2020 г.)До Git 2.28 (3 квартал 2020 г.)
--prepare-p4-only
опция " " должна была останавливаться после воспроизведения одного набора изменений, но продолжала работать (по ошибке?)См. Commit 2dfdd70 (12 мая 2020 г.) Бена Кина (
seraphire
) .(Объединено Junio C Hamano -
gitster
- в коммите 7a8fec9 , 02 июня 2020 г.)источник