I've been using Perforce for a number of years. I'd like to switch to using git for my personal code, but all of the git tutorials that I've seen either assume that you'e a complete source control n00b (which makes them incredibly tedious) or that you're used to svn (which I'm not).
I know p4, and I also understand the idea behind a distributed source control system (so I don't need a sales pitch, thanks). What I'd like is a translation table from p4 command to equivalent git commands, as well as the "can't live without" commands that have no p4 equivalent.
Since I suspect every p4 user uses a different subset of p4, here are some of the things I regularly do in p4 that I'd like to be able to do in git that aren't immediately obvious from the docs I've looked at:
- create multiple pending changelists in a single client. (
p4 change
) - edit a pending changelist. (also
p4 change
) - see a list of all of my pending changelists (
p4 changes -s pending
) - list of all of the changed files in my client (
p4 opened
) or in a pending changelist (p4 describe
) - see a diff of a pending changelist (I use a wrapper script for this which uses
p4 diff
andp4 describe
) - for a given file, see which submitted changelists affected which lines (
p4 annotate
) - for a given file, see a list of the descriptions of the changelists that affected the file (
p4 log
) - submit a pending changelist (
p4 submit -c
) - abort a pending changelist (
p4 revert
)
A lot of these revolve around "changelists". "changelist" is p4 terminology. What's the git equivalent term?
It sounds like branches might be what git users use in place of what p4 calls changelists. A bit confusing, since p4 also has something called a branch though they seem to be only vaguely related concepts. (Though I always thought p4's concept of a branch was pretty weird it is different yet again from the classic RCS concept of a branch.)
Anyway... I'm not sure how to accomplish what I normally do in p4 changelists with git's branches. In p4 I can do something like this:
$ p4 edit a.txt
$ p4 change a.txt
Change 12345 created.
At this point I have a changlist that contains a.txt. I can edit the description and continue working without submitting the changelist. Also, if it turns out that I need to make some changes to some other files, like say a bugfix in some other layer of the code, I can do that in the same client:
$ p4 edit z.txt
$ p4 change z.txt
Change 12346 created.
Now I have two separate changelists in the same client. I can work on these concurrently, and I don't need to do anything to "switch between" them. When it comes time to commit, I can submit them separately:
$ p4 submit -c 12346 # this will submit the changes to z.txt
$ p4 submit -c 12345 # this will submit the changes to a.txt
I can't figure out how to replicate this in git. From my experiments, it doesn't appear that git add
is associated with the current branch. As far as I can tell, when I git commit
it's going to commit all files that I git add
-ed no matter what branch I was in at the time:
$ 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
In this example, the aardvark and zebra branches seem to contain exactly the same set of changes, and based on the output of git status
it appears that doing a commit in either will have the same effect. Am I doing something wrong?