Web lists-archives.com

Re: "groups of files" in Git?

For starters, let me say that I consider myself a mere advanced 
beginner Git user, and I haven`t used Perforce ever before (did some 
reading now), but still, for what it`s worth, here are my thoughts, 
please bare with me :)

Do feel free to correct me if I miss something.

On 11/07/2017 19:39, Lars Schneider wrote:
>> On 11 Jul 2017, at 17:45, Nikolay Shustov <nikolay.shustov@xxxxxxxxx> wrote:
>> Hi,
>> I have been recently struggling with migrating my development workflow
>> from Perforce to Git, all because of the following thing:
>> I have to work on several features in the same code tree parallel, in
>> the same Perforce workspace. The major reason why I cannot work on one
>> feature then on another is just because I have to make sure that the
>> changes in the related areas of the product play together well.
>> With Perforce, I can have multiple changelists opened, that group the
>> changed files as needed.
>> With Git I cannot seem to finding the possibility to figure out how to
>> achieve the same result. And the problem is that putting change sets
>> on different Git branches (or workdirs, or whatever Git offers that
>> makes the changes to be NOT in the same source tree) is not a viable
>> option from me as I would have to re-build code as I re-integrate the
>> changes between the branches (or whatever changes separation Git
>> feature is used).
>> Build takes time and resources and considering that I have to do it on
>> multiple platforms (I do cross-platform development) it really
>> denominates the option of not having multiple changes in the same code
>> tree.
>> Am I ignorant about some Git feature/way of using Git that would help?
>> Is it worth considering adding to Git a feature like "group of files"
>> that would offer some virtutal grouping of the locally changed files
>> in the checked-out branch?
> Interesting question that came up at my workplace, too.
> Here is what I suggested:
> 1. Keep working on a single branch and make commits for all features
> 2. If you make a commit, prefix the commit message with the feature name
> 3. After you are done with a feature create a new feature branch based on
>    your combined feature branch. Use `git rebase -i` [1] to remove all
>    commits that are not relevant for the feature. Alternatively you could
>    cherry pick the relevant commits [2] if this is faster.
> I wonder what others think about this solution. Maybe there is a better
> solution that I overlooked?
> - Lars
> [1] https://robots.thoughtbot.com/git-interactive-rebase-squash-amend-rewriting-history
> [2] http://think-like-a-git.net/sections/rebase-from-the-ground-up/cherry-picking-explained.html

This "single branch, related commits" approach is exactly what came 
to my mind as well.

But, isn`t Perforce "changelist" an "atomic" group of changes - like 
"commit" in Git, "changeset" in Team Foundation Version Control, 

If so, it would mean that this "multiple pending changelists" flow 
would/should be translated to "multiple pending commits" in Git, 
where in the end _a single_ Perforce "changelist" is _a single_ Git 

Might be this is where the confusion is coming from, trying to fit 
natural Git "multiple commits per feature" (but "single feature per 
branch") concept into a "single changelist per feature" Perforce 
concept, described/required here?

I don`t think there is a firm concept of such "multiple pending 
commits" in Git, but the point is the author is having multiple 
changelists/commits, and it actively updates them (the _same ones_), 
until they`re ready to be merged (submitted, in Perforce)... which 
you can do in Git, and might be quite easily :)

So... In Git, you can create a separate commit for each changelist 
you have in Perforce (all these commits being on the same branch, as 
desired). Then, when you would have wanted to "update" the pending 
Perforce changelist (not sure what the corresponding command is in 
Perforce), you would just `git commit` your current state with 
additional "--squash" or "--fixup" parameters (depending on if you 
would like to add more description to existing/original commit 
message, or not), and the original commit SHA1.

In the end, when everything is tested together and you would like to 
commit features separately (like submitting changelists in Perforce), 
you would just need to `git rebase -i --autosquash` your branch, 
where Git would squash all your "update" commits (fixup/squash ones, 
that is) to the original/initial ones you made as per your 
changelists/features. No need for manual rearranging, cherry-picking, 
or whatever.

An example flow, with two "changelists" for two features (I`ll be 
using capital letters A, B, C... instead of commit SHA1, for 

	... do some "Feature 1" work...
	$ git commit -m "Feature 1"
	... do some "Feature 2" work...
	$ git commit -m "Feature 2"
	... do some "Feature 1" work...
	$ git commit --fixup A
	... do some "Feature 1" work...
	$ git commit --fixup A
	... do some "Feature 2" work...
	$ git commit --squash B
	... do some "Feature 1" work...
	$ git commit --fixup A
	... do some "Feature 1" work...
	$ git commit --squash A
	... do some "Feature 2" work...
	$ git commit --fixup B

Branch history would look something like this (H is latest commit):

	H fixup! Feature 2
	G squash! Feature 1
	F fixup! Feature 1
	E squash! Feature 2
	D fixup! Feature 1
	C fixup! Feature 1
	B Feature 2
	A Feature 1

When you finally do `git rebase -i --autosquash A^`, you should get a 
list like this[1]:

	pick A Feature 1
	fixup C fixup! Feature 1
	fixup D fixup! Feature 1
	fixup F fixup! Feature 1
	squash G squash! Feature 1
	pick B Feature 2
	squash E squash! Feature 2
	fixup H fixup! Feature 2

Once rebase is finished, you`ll end up with branch history looking 
like this:

	B' Feature 2
	A' Feature 1

... where commits A, C, D, F and G have been squashed into a single 
commit A', and commits B, E and H have been squashed into a single 
commit B'. These two single commits should correspond to your two 
Perforce changelists.

Now you can merge your commits separately, as desired ("submit" the 

You can even first rearrange/split/squash them further, or make 
separate branches out of them, whatever you find appropriate - you 
can do whatever you like to them while they`re your local commits 
("pending changelists"), before making them live/visible for other 
users as well (merge them to a public branch, "submit changelist").

p.s. Doesn`t the flow required here look similar to Mercurial patch
"queues" approach (again, resembling "quilt" functionality)? If so, 
"Guilt"[2] may be an option here as well... if the described flow 
can`t be altered a bit to align better with Git itself, might be 
profiting on the side of overall workflow simplicity ;)

[1] Having commits automatically grouped/ordered, you can even 
    replace some "fixup" and "squash" with "reword", for example, so 
    those commits are kept as separate ones, providing you a chance 
    to edit their messages.
[2] http://repo.or.cz/w/guilt.git