Git для пользователей Perforce - PullRequest
82 голосов
/ 07 сентября 2010

Я использую Perforce уже несколько лет.Я хотел бы переключиться на использование git для моего личного кода, но все учебники по git, которые я видел, предполагают, что вы полностью управляете исходным кодом n00b (что делает их невероятно утомительными) или что вы привыклиsvn (которым я не являюсь).

Я знаю p4, и я также понимаю идею, лежащую в основе системы управления распределенным исходным кодом (так что мне не нужно коммерческое предложение, спасибо).Мне бы хотелось, чтобы таблица перевода из команды p4 в эквивалентные команды git, а также команды «не может жить без», не имеющие эквивалента p4.

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

  1. создать несколько ожидающих изменений в одном клиенте.(p4 change)
  2. редактировать ожидающий список изменений.(также p4 change)
  3. см. список всех моих ожидающих изменений (p4 changes -s pending)
  4. список всех измененных файлов в моем клиенте (p4 opened) или всписок ожидающих изменений (p4 describe)
  5. см. различие ожидающего списка изменений (для этого я использую скрипт-обертку, который использует p4 diff и p4 describe)
  6. для данного файла, см.какие представленные списки изменений повлияли на то, какие строки (p4 annotate)
  7. для данного файла, см. список описаний списков изменений, которые повлияли на файл (p4 log)
  8. представить отложенный список изменений(p4 submit -c)
  9. отменить ожидающий список изменений (p4 revert)

Многие из них вращаются вокруг "списков изменений".«список изменений» - это терминология p4.Что такое эквивалент в git?

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

В любом случае ... Я не уверен, как добиться того, что я обычно делаюв p4 списки изменений с ветками git.В p4 я могу сделать что-то вроде этого:

$ p4 edit a.txt
$ p4 change a.txt
Change 12345 created.

На данный момент у меня есть список изменений, который содержит .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

В этом примереВетви aardvark и zebra, по-видимому, содержат абсолютно одинаковый набор изменений, и, основываясь на выводе git status, кажется, что выполнение коммитов в любом из них будет иметь одинаковый эффект.Я что-то не так делаю?

Ответы [ 6 ]

68 голосов
/ 07 сентября 2010

Я не очень часто использовал перформанс, поэтому это может быть не совсем перевод 1: 1.С другой стороны, системы управления исходным кодом, такие как git и mercurial, в любом случае имеют другой рабочий процесс, поэтому в действительности не должно быть (и не должно быть) перевода 1: 1.Во всяком случае, здесь идет:

  • Создайте несколько ожидающих изменений списки -> Вместо этого используйте ветви.В git ветки легкие и быстрые, создание занимает менее секунды, а объединение обычно менее двух секунд.Не бойтесь ветвления и часто перебазируйте.

    git branch new-branch-name
    git checkout new-branch-name
    

    Или делайте все это в одной строке:

    git checkout -b new-branch-name
    
  • См. Список всех ожидающих изменений-> Поскольку эквивалентом нескольких ожидающих изменений является несколько веток, просто просмотрите ветки:

    git branch
    

    Если вы также хотите просмотреть удаленные ветки:

    git branch -a
    

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

  • Список всех измененных файлов -> Для одного ожидающего изменения списка изменений в конкретной ветке git имеет понятие индекса или кэша.Чтобы зафиксировать изменение, вы должны сначала добавить файлы в этот индекс.Это позволяет вам вручную выбирать, какая группа файлов представляет отдельное изменение, или игнорировать нерелевантные файлы.Чтобы узнать, какие файлы добавлены или нет к этому индексу, просто сделайте:

    git status
    
  • См. Различие ожидающего списка изменений -> Есть две части этого.Сначала посмотрите разницу между рабочим каталогом и индексом:

    git diff
    

    Но если вы хотите узнать разницу между тем, что вы печатаете сейчас, и последним коммитом, тогда вы действительно запрашиваете разницу междурабочий каталог + индекс и ГОЛОВКА:

    git diff HEAD
    
  • Для данного файла посмотрите, какие представленные списки изменений повлияли на какие строки -> Это просто:

    git blame filename
    

    или даже лучше, если вы находитесь в оконной среде:

    git gui blame filename
    

    Git GUI занимает больше времени для анализа файла (он был написан на tcl вместо C), но у него есть много полезных функций, включая возможность"путешествие во времени" назад в прошлое, нажав на идентификатор фиксации.Я только хотел бы, чтобы они реализовали функцию «путешествия во времени» в будущее, чтобы я мог выяснить, как, наконец, данная ошибка будет исправлена;см. список описаний списков изменений, которые повлияли на файл -> также просто:

    git log filename
    

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

  • Отправьте ожидающий список изменений -> Также просто:

    git commit
    

См. Мой ответ на предыдущий вопрос, чтобы увидетьмой типичный рабочий процесс git: Learning Git.Нужно знать, нахожусь ли я на правильном пути

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


Дополнительный ответ:

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

git checkout -b new-feature-a

Теперь вы можете редактировать файл a.txt.Для одновременной работы с другой функцией выполните:

git checkout master
git checkout -b new-feature-z

Теперь вы можете редактировать файл z.txt.Чтобы вернуться к a.txt:

git checkout new-feature-a

Но подождите, в new-feature-z есть изменения, и git не позволит вам переключать ветки.На данный момент у вас есть два варианта.Первый - самый простой, передайте все изменения в текущую ветку:

git add .
git commit
git checkout new-feature-a

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

git stash

Теперь вы можете переключиться на ветку new-feature-a. Чтобы вернуться к коду, над которым вы работали, просто вставьте тайник:

git checkout new-feature-z
git stash pop

Когда все будет сделано, объедините все изменения с мастером:

git merge --no-ff new-feature-a
git merge --no-ff new-feature-z

Поскольку слияния происходят так быстро и легко (просто потому, что конфликты настолько редки, а разрешение конфликтов, когда оно происходит, не слишком сложно), мы используем ветки в git для всего.

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

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

git checkout -b dev-config

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

git add .
git commit

Теперь каждая новая ветка может начинаться с ветки dev-config вместо master:

git checkout dev-config
git checkout -b new-feature-branch

Как только вы закончите, удалите изменения в dev-config из new-feature-branch с помощью интерактивной перебазировки:

git rebase -i master

Удалите коммиты, которые вы не хотите, затем сохраните. Теперь у вас есть чистая ветка без пользовательских настроек. Время слиться с мастером:

git checkout master
git merge --no-ff new-feature-branch
# because master have changed, it's a good idea to rebase dev-config:
git checkout dev-config
git rebase master

Следует отметить, что удаление изменений с помощью git rebase -i работает даже тогда, когда все изменения происходят в одном и том же файле. Git запоминает изменения, а не содержимое файла *.

* примечание: на самом деле, технически не совсем верно, но как пользователь это то, что он чувствует


Более дополнительный ответ:

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

Во-первых, слово о влиянии дешевого ветвления и изменяемой истории на ваш рабочий процесс. Когда я использовал CVS и SVN, я всегда неохотно соглашался. Это связано с тем, что фиксация нестабильного кода неизбежно приведет к созданию рабочего кода других людей. Но с мерзавцем я потерял этот страх. Это потому, что в git другие люди не получат мои изменения, пока я не объединю их с мастером. Так что теперь я обнаруживаю, что я записываю код каждые 5 строк Вам не нужно совершенное предвидение, чтобы совершить. Вам просто нужно изменить свое мышление: commit-to-branch == add-to-changeset, merge-to-master == commit-changeset.

Итак, вернемся к примерам. Вот как бы я это сделал. Скажем, у вас есть ветка new-feature-z, и вы хотите проверить ее с new-feature-a. Я бы просто создал новую ветку для тестирования:

# assume we are currently in branch new-feature-z
# branch off this branch for testing
git checkout -b feature-z-and-feature-a
# now temporarily merge new-feature-a
git merge --no-ff new-feature-a

Теперь вы можете проверить. Если вам нужно что-то изменить, чтобы Feature-Z работал с Feature-A, сделайте это. Если это так, вы можете объединить изменения в соответствующую ветку. Используйте git rebase -i, чтобы удалить несущественные изменения из слияния.

В качестве альтернативы, вы также можете использовать git rebase для временного изменения базы new-feature-z для указания на new-feature-a:

# assume we are currently in branch new-feature-z
git rebase new-feature-a

Теперь история ветвей модифицируется так, что new-feature-z будет основываться на new-feature-a вместо master. Теперь вы можете проверить. Любые изменения, внесенные в эту ветку, будут принадлежать ветви new-feature-z. Если вам нужно изменить new-feature-a, просто переключитесь обратно на него и выполните ребаз, чтобы получить новые изменения:

git checkout new-feature-a
# edit code, add, commit etc..
git checkout new-feature-z
git rebase new-feature-a
# now new-feature-z will contain new changes from new-feature-a

Когда вы закончите, просто вернитесь к мастеру, чтобы удалить изменения из new-feature-a:

# assume we are currently in branch new-feature-z
git rebase master

Не бойтесь начать новую ветку. Не бойтесь начать одноразовую ветку. Не бойтесь выбрасывать ветви. А поскольку слияния == отправить и зафиксировать == добавить-для-изменения, не бойтесь часто совершать. Помните, что commit - это лучший инструмент для отмены действий разработчика.

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

1 голос
/ 14 августа 2013

В git есть более легкая альтернатива, которая может стать частью вашего рабочего процесса; используя область подготовки git.

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

Вы можете зафиксировать определенные файлы из командной строки с помощью:

git commit a.txt
git commit z.txt

Или сначала явно разместите файлы:

git add a.txt
git commit
git add z.txt
git commit

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

В этом рабочем процессе следует помнить о небольшом предостережении. Если вы вносите изменения A и B в файл, тестируете файл, затем фиксируете A, тогда вы не тестировали этот коммит (независимо от B).

1 голос
/ 07 апреля 2012

Как и вы, я страдаю из-за отсутствия концепции "списка изменений", которая не совсем совпадает с ветками git.

Я бы написал небольшой скрипт, который создаст файл списка изменений со списком файлов в этом списке изменений.

Другая команда для отправки только определенного списка изменений, просто вызвав git commit -a @ change_list_contents.txt и затем "git commit"

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

1 голос
/ 07 сентября 2010

У меня недостаточно опыта p4, чтобы составить реальную шпаргалку, но есть хотя бы некоторые сходства, к которым можно прибегнуть. P4 "changeset" - это git "commit".

Изменения в вашем локальном рабочем пространстве добавляются в «индекс» с помощью git add, а индекс позже фиксируется с git commit. Таким образом, индекс - это ваш ожидающий изменения список для всех намерений и целей.

Вы смотрите на изменения с git diff и git status, где git diff обычно показывает изменения между рабочей областью и индексом, но git diff --cached показывает изменения между индексом и хранилищем (= ваш ожидающий список изменений).

Для получения более подробной информации, я рекомендую http://progit.org/book/. Так как вы в целом знаете управление версиями, вы, вероятно, можете просмотреть его и извлечь информацию, относящуюся к git ...

0 голосов
/ 05 июля 2018

Достаточно широко использовав как Perforce, так и git, я вижу только один способ приблизиться к спискам изменений Perforce с помощью git.

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

Списки изменений Perforce разрешают рабочий процесс, который просто не имеет аналогов в git. Рассмотрим следующий рабочий процесс:

Check out a branch
Modify file A and add it to changelist 1
Modify file B and add it to changelist 2

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

Самое близкое приближение, которое я вижу, это использовать git add . -p, а затем использовать подкоманды 'a' и 'd' для выбора или отклонения целых файлов. Однако это не совсем то же самое, и различие здесь связано с фундаментальным несоответствием в общем способе работы двух систем.

Git (и subversion, а не то, что это имеет значение для этого обсуждения) позволяют изменять файл, не сообщая об этом никому заранее. Вы просто изменяете файл, а затем позволяете git разобраться во всем, когда вы фиксируете изменения. Perforce требует от вас активной проверки файла до того, как изменения будут разрешены, и по этой причине списки изменений должны существовать. По сути, Perforce требует добавления файла в индекс перед его изменением. Отсюда необходимость наличия нескольких списков изменений в Perforce, а также причина, по которой git не имеет эквивалента. Они просто не нужны.

0 голосов
/ 10 сентября 2010

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

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

...