The biggest difference between git and p4, which none of the existing answers address, is that they use different units of abstraction.
- In git, the abstraction is the patch (aka diff, aka changeset). A commit in git is essentially the output of running
diff
between the previous and current state of the files being committed.
- In perforce, the abstraction is the file. A commit in p4 is the full content of the files in the commit at that point in time. This is organised into a changelist, but the revisions themselves are stored on a per-file basis, and the changelist simply collects different revisions of the files together.
Everything else flows from this difference. Branching and merging in git is painless because, from the perspective of git's abstraction, every file can be fully reconstructed by applying a set of patches in order, and therefore to merge two branches, you just need to apply all the patches on the source branch that aren't present in the target branch to the target branch in the correct order (assuming there are no patches on both branches that overlap).
Perforce branches are different. A branch operation in perforce will copy files from one subfolder to another, and then mark the linkage between the files with metadata on the server. To merge a file from one branch to another (integration
in perforce terms), perforce will look at the complete content of the file at the 'head' of on the source branch and the complete content of the file at the head of the target branch and if necessary merge using a common ancestor. It is unable to apply patches one by one like git can, which means manual merges happen more often (and tend to be more painful).