1

I am new to git and am currently trying to learn as much as I can about it.

I think the concept of it is fantastic and extremely valuable to any developer's workflow.

I am a data scientist who programs in R, and due to the nature of my work, I work on several projects simultaneously for several people/departments.

I find that I often need to switch back and forth between said projects due to ad-hoc queries / people losing things / people urgently needing to know something, and as such it got me thinking what the best practice is around switching branches.

What lead me to ask this question was that I am finding (especially recently) that I tend to modify several files from several projects in a short amount of time (sometimes in 30 minutes I can modify files from six different projects), and then when I go to switch branches to work on something that I had scheduled to work on, I am presented with the problem of either stashing or committing my changes to the current branch before being allowed to switch.

The problem is that I only wish to commit some of those changes (usually just a single file) to the specific branch that I am currently working on, but of course I can't switch branches without either stashing - or discarding - my changes first.

As such, I want to know if it is good/best practice to immediately commit new changes on their respective branches as soon as I have finished with them and then switch back to my master/other-work branch immediately afterwards, or whether there is another way that typically works best for the majority of people.

My question is this: should I switch branches each time I am finished with a project / set of changes, even if I change just a single file, or should I be doing something else?

For example, if I am working on ProjectX and then somebody asks me to do something for them on ProjectY, should I switch from project-x-branch to project-y-branch, make the changes, commit them and switch back to project-x-branch and continue or is there a better way to handle such scenarios?

The idea I have in mind is so that when I check my working copy, there are only one or two files to commit to the branch that I am working on as opposed to several that aren't related to my current branch.

I appreciate that stashing is designed for this very purpose (at least I think that's what it is for - please correct me if I am wrong) but nevertheless I feel that it is better practice to (ideally) avoid stashing altogether.

I fully expect that committing and switching branches each time I am finished on an update/modification is a very simple and useful habit to adopt, but before I begin implementing said habit, I would really like to know if there might be a better way to handle this.

I have checked the potential duplicate of this question and it doesn't quite seem like the same problem because mine is not a case of experiencing bugs, but more a case of having to randomly change code from one or two projects (where I don't necessarily need to keep the changes) as they don't add value. The changes are small, such as extracting some other piece of information instead of / in addition to what they were already extracting.

  • Possible duplicate of When to commit work in git? – gnat Jul 19 '18 at 8:39
  • You can always commit (parts of) your working folder to a new branch, on the other hand, you can also always commit an "undo" of work-in-progress things that you decide against – Caleth Jul 19 '18 at 8:39
  • see also: Is it ever OK to commit non-working code? – gnat Jul 19 '18 at 8:40
  • 1
    Are these projects all related? Why are they different branches of a single repo and not different repos? – mmathis Jul 19 '18 at 14:23
  • I direct you to the first line: I am new to git... Also, when I set this repo up some time ago (on the recommendation of a colleague) I had a single project in there; since then I have added several others and have only started working with git in the last two weeks. I considered creating new repos for each project and this is something that I may adopt soon. Nevertheless, this doesn't directly relate to my question; even if I did have different repos, I still want to know if it is best practice to commit changes to project-x-branch before switching to project-y-branch or to stash first. – MusTheDataGuy Jul 19 '18 at 15:20
2

You should commit when ever your project compiles (and passes all UnitTests).

This way you'll commit every 2 minutes (in average). So you are only 2 minutes away from switching branch or leaving for home. This there is no nee to use the stash (most of the time).

This in best done in conjunction with TDD since this gives you two distinct events to commit: after you made the last (one and only failing) test "green" and after "refactoring", before writing the next test.


still I don't see the point of commiting that often, – Walfrat

The biggest benefit is when you rebase your changes to integrate with your upstream: git applies every commit in separation (unlike it does when "merging" where it only applies the resulting changes). This has some benefits:

  1. since the commits are (very) small there is a very low chance for conflicts.
  2. if there are conflicts its easy to find out what the result should be, since the changes are so small.
  3. you can verify your conflict resolution by running your unit tests before continuing the rebase.
  4. If you later have to find out when you introduced a certain behavior you can just search through your commit messages. The commit found only has the relevant changes. You don't need further investigation which changes in the commit are relevant.

in average I commit once or twice a day. I fail to see how I can perform meaningful commit on a lower scale. – Walfrat

When doing TDD the the end of the micro cycle is a somewhat "natural event" to commit:
You have your project in a deliverable state.

If there is a need to "rollback" you most likely want to return to such a state knowing that all features implemented so far really work. When doing TDD this typically is every 30 seconds, sometimes longer and about 2 minutes in average.

The commit message would describe the tests assumption on the production code it verifies.

  • 1
    @Walfrat " How the hell do I do if i want to rollback something ? I won't ever be able to identify the correct point of rollback." use branches and/or meaningful commit messages. The smaller an commit is the easier it is to find a meaningful commit message. – Timothy Truckle Jul 19 '18 at 9:13
  • Additional benefits to frequent commits. (1) encourages discipline in making small, non-breaking changes, which in turn encourages simpler implementations with less redundant fluff. (2) facilitates faster integration (and ideally also deployment) cycles and therefore faster feedback loops. (3) facilitates much easier bug-hunting using tools like git bisect as smaller commits are easier to reason about once offending commits have been identified... – Ant P Jul 19 '18 at 14:30
  • Note though that none of these benefits imply a need to rebase rather than merge. Merges still retain all commit history. – Ant P Jul 19 '18 at 14:30
2

Git has three relevant features here:

  1. Git does not impose a workflow, and encourages (requires?) you to find your own.
  2. Git is distributed: what you do locally doesn't affect other people.
  3. Git has super cheap commits (in fact stashing creates a commit, it just doesn't add it to the branch).

It is perfectly fine to create lots of micro-commits, even if they do not represent a working state of your software. Before you git-push your work to make it visible for others, you can git-rebase your commits to squash (combine), re-order, or re-phrase them. This allows you to work how you like, but later organize that work in a way that makes sense to others.

A variant of this is to commit a WIP (work in progress) and continuously git commit --amend with new changes. This shows fewer commits in your history than separate micro-commits. Once the commit is ready you can amend it one last time to fix up the commit message. This is my preferred approach.

The stash is just a convenient way to create and re-apply a WIP commit without directly affecting your current branch. This is a matter of taste, I personally do not like the stash because it provides little visibility into the stashed changes.

Another great alternative you can consider is checking the project out multiple times into separate directories. All checkouts can still share the same local git database, but can work on different branches. The easy way to do this is to git-clone the local repository instead of a remote URL, in which case the repositories are conceptually separate. The more sophisticated approach is to use git-worktree. The documentation shows this wonderful example which creates a new worktree with a new branch:

You are in the middle of a refactoring session and your boss comes in and demands that you fix something immediately. You might typically use git-stash to store your changes away temporarily, however, your working tree is in such a state of disarray (with new, moved, and removed files, and other bits and pieces strewn around) that you don’t want to risk disturbing any of it. Instead, you create a temporary linked working tree to make the emergency fix, remove it when done, and then resume your earlier refactoring session.

$ git worktree add -b emergency-fix ../temp master
$ pushd ../temp
# ... hack hack hack ...
$ git commit -a -m 'emergency fix for boss'
$ popd
$ git worktree remove ../temp

The drawback? This feature is still experimental and the extra checkout might consume significant space (and time, if the new worktree implies a clean build).

So experiment a bit, and find a personal Git workflow that works for you. Once you've settled in, consider adding aliases (shortcuts) for your common operations.

1

You can just have two directories containing the complete git repository. Imagine you had two computers, and you do your main work on one, and when you get interrupted you use the other one. You can do the same by just using two directories. So there is no need to switch projects at all.

How you best organise commits in your main work is up to you. If you do code reviews (as you should) then every commit should be easy enough to be easily reviewable. "Every time it compiles" is too often; "every time a meaningful change is made" is better, "once the complete feature is done" is much too rare.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.