Jump to content
David Schwartz

git workflow question

Recommended Posts

Maybe "git diff" and "git blame" would show something useful. You are a team of developers and go with "something is messed up" statements?

Usually this come from the clients.

 

 

  • Like 2

Share this post


Link to post
On 9/6/2020 at 3:23 AM, David Schwartz said:

Commit branch to the repository

> git checkout <ticket-branch-name>    ...switch to the ticket branch if not already there

> git pull origin master    

> git checkout master    ...switch to master

> git pull    ...pull changes from repo, resolve any conflicts

> git merge <ticket-branch-name>    ...merge the branch into the local master

> git push origin master    ...merge local master into remote master

I posted this earlier, and I'm convinced there's a problem with it.

 

We went through and made a bunch of changes to a few files yesterday while in a specific branch. 

 

Then we used this process to effectively "check-in" the code -- ie., sync it with master.

 

Today I went in and started to do some work where I left off, and got a bunch of errors.

 

I was working in master, and started looking at the code, and none of yesterday's work was there!

 

I freaked out, because the files pushed into production were from master, and they're wrong. So I started making the changes again, and then realized I was still in master.

 

So I tried to checkout the previous branch and got an error warning that it would overwrite the two files I'd been trying to update again. I just renamed them and ran the checkout again, and it worked. 

 

I examined the files and ... lo and behold ... there were my changes! WTF???

 

What's wrong with this process? (NOTE: I did not come up with it, a colleague I work with did, and he swears by it. I swear AT it. There something wrong with it!)

Share this post


Link to post
7 hours ago, David Schwartz said:

> git checkout <ticket-branch-name>    ...switch to the ticket branch if not already there

> git pull origin master    

> git checkout master    ...switch to master

> git pull    ...pull changes from repo, resolve any conflicts

> git merge <ticket-branch-name>    ...merge the branch into the local master

> git push origin master    ...merge local master into remote master

I don't do these thing from the command line, so I may be wrong, but it seems to me that you're:

  1. Switching the active branch to <ticket-branch-name>.
  2. Pulling the remote master onto it.
  3. Switching to master.
  4. Pulling the remote master again.
  5. Merging <ticket-branch-name> into local master.
  6. Pushing local master to remote master.

I can't understand why you're doing 1-2. In particular #2 seems wrong. I think you may be creating foxtrot merges.

Did you forget to commit your changes to <ticket-branch-name> before you switched to master?

 

You haven't specified if your local branches are setup to track the corresponding remote ones. If they're not, and you haven't adjusted your git commands for that, then you might be working with detached heads.

 

Anyway, here's what (I think) I would do:

  1. Switch to local <ticket-branch-name>:
    git checkout <ticket-branch-name>
  2. Make my changes...
  3. Stage my changes:
    git add <files>
  4. Commit changes to local <ticket-branch-name>:
    git commit -m "blah blah"
  5. Fetch master from remote:
    git fetch (or just: git fetch --all)
    Note that you you might need to do git fetch origin master:master depending on if your local master is tracking the remote master or not.
  6. Switch to master:
    git checkout master
  7. Clear all changes from working directory:
    git reset --hard
  8. Pull from remote master:
    git pull origin
  9. Merge local <ticket-branch-name> into local master:
    git merge <ticket-branch-name>
  10. Push local master to remote master:
    git push origin master

Again: I don't use the command line so the above is just my understanding of what my GUI tool does for me. If you were using a GUI Git tool it would be much more clear to you what's going on.

  • Like 1

Share this post


Link to post

Thanks for this. 

 

I'm not clear how on 7, "git reset --hard" clears changes from the working directory. Don't git commands affect the entire repo? (Our repo includes the entire virtual drive, ~850 folders.)

 

What git GUI tool do you prefer? We only have free stuff available, but I did use Tower for a while a couple of years ago. 

 

I have the right-click Git GUI option, along with Tortise git.

---------

In a more abstract sense, I think what they're trying to accomplish here is to use git for two purposes.

 

One is obviously to keep a version history of our work. They say that if something in Production turns out to be trashed, we need to be able to roll-back to the previous version.

 

What's happening right now (using that sequence I showed above) is that git is reverting things right before we push the files into production, and our changes are lost. Rolling-back doesn't help -- our changes are not in Master. However, I discovered they're still in the local branch, as long as I haven't deleted it. I think it's b/c of something wrong we're doing above.

 

The other purpose is to use git to distribute changes to everybody's local machines so we're all in sync with all of the latest updates. The theory being if one of us gets hit by a proverbial truck (or we catch COVID), someone can come in and start working where they left off because they've got all of the latest files (well, those that were committed and pushed properly, anyway).

 

This has two negative consequences that I've seen. One is that two different people working in the same folder at different times can cause conflicts to arise fore everybody else who never touched anything in those folders. This is a time-related artifact that only happens if you do a pull in the time interval when the conflict arose and was resolved. If you have a team of 50 people and a conflict arises between two of them, I don't see why the other 48 are forced to even see it let alone deal with it on their machines. This is supposedly a "feature" of git. (Maybe this is also a reflection of how we keep pushing stuff to Master instead of maintaining a dev branch. We do quick turnaround stuff on isolated tasks, so dev branches are meaningless.) 

 

The second is the complexity added when we're modifying the same files for different tickets that are for independent needs but happen to address data in the same files (and folder).

 

I personally think it would be a whole lot easier to use something like Dropbox for this latter purpose.

 

sorry if I'm sounding redundant, but I hate having to spend my weekends cleaning up messes caused during the week b/c nobody at work seems to know what the problem is (or believe one even exists).

Share this post


Link to post
1 hour ago, David Schwartz said:

I'm not clear how on 7, "git reset --hard" clears changes from the working directory. Don't git commands affect the entire repo? (Our repo includes the entire virtual drive, ~850 folders.)

It discards changes to all tracked files. Basically it makes sure that what you have on disk matches what's in your branch.

You can also do a mixed reset. That moves the index in your commit history but keeps whatever you have on disk. Then there's a soft reset but I can't remember what that does as I never use it.

 

The reason I'm doing a reset is that otherwise pull will do a merge with whatever I have on disk and that isn't what I want. I'm not actually doing anything since my tool does all this for me, but you get the picture.

 

58 minutes ago, David Schwartz said:

What git GUI tool do you prefer?

Personally I prefer Atlassian SourceTree. I have Tortoise Git installed as well because there are a few things it does better (Blame for one). I've not tried any of the commercial GUI clients.

 

There was a thread here a few weeks back where different Git clients were discussed.

  • Thanks 1

Share this post


Link to post
6 hours ago, Dalija Prasnikar said:

I found this answer on Stack Overflow about merging branch to master. Maybe it will help. https://stackoverflow.com/a/29048781/4267244

I'm not sure I agree with it.

As I read it, and I may well be misunderstanding it, it assumes that when I merge my 1000 commit feature branch into master that I want all 1000 commits to appear in the master commit history. Well I definitely don't. The 1000 commits are the sausages being made and I only want the finished sausage in the master commit history.

 

There's also this:

Quote

The only thing you need to avoid is: never use rebase on public branch, like master branch

What it should have said is: never rebase a public branch.

It's perfectly safe and normal to rebase a private branch on a public branch. Assuming on=onto. Maybe that's what he meant.

Share this post


Link to post
24 minutes ago, Anders Melander said:

I'm not sure I agree with it.

As I read it, and I may well be misunderstanding it, it assumes that when I merge my 1000 commit feature branch into master that I want all 1000 commits to appear in the master commit history. Well I definitely don't. The 1000 commits are the sausages being made and I only want the finished sausage in the master commit history.

 

That part is purely optional. You can do as you please. But when you are merging without rebasing, you also get the whole sausage, unless you squash.

 

24 minutes ago, Anders Melander said:

There's also this:

What it should have said is: never rebase a public branch.

It's perfectly safe and normal to rebase a private branch on a public branch. Assuming on=onto. Maybe that's what he meant.

Yes, never rebase a public branch is more clearer. That is what was meant with that sentence. It is never call rebase when you are on public branch. In other words when active branch is public branch.

  • Like 1

Share this post


Link to post
24 minutes ago, Dalija Prasnikar said:

But when you are merging without rebasing, you also get the whole sausage, unless you squash.

Squash? But that's a rebase thing, right? So how can you squash without rebase?

 

Anyway. Let's say I have my 'master' commit history:

1. Initial commit

2. Made some changes

3. Fixed some changes

 

At commit #2 I branch 'master' into 'FooBar' and make "a few" commits to that branch:

1. Experimental stuff

2. Enhancements

...

999. Refactorings

1000. Updated easter egg

 

Now I merge my 1000 commit branch into master (resolve conflicts etc):

4. Merge branch 'FooBar' into 'master'

 

And push. So the now 'master' commit history will read:

1. Initial commit

2. Made some changes

3. Fixed some changes

4. Merge branch 'FooBar' into 'master'

 

Are you saying that you'd want the whole 1000 'FooBar' commits to appear in the 'master' commit history?

I can see that if you don't have 'FooBar' pushed to the remote then the history will be lost, in which case it makes sense, but if you have pushed it, then there's no need to duplicate that history in 'master'.

Share this post


Link to post
9 hours ago, Anders Melander said:

Squash? But that's a rebase thing, right?

Hmm, no, squash is just join all commits into one.

 

Share this post


Link to post
10 hours ago, Anders Melander said:

Squash? But that's a rebase thing, right? So how can you squash without rebase?

merge --squash (if I am not mistaken, never used it as I am always rebasing)

10 hours ago, Anders Melander said:

Are you saying that you'd want the whole 1000 'FooBar' commits to appear in the 'master' commit history?

I can see that if you don't have 'FooBar' pushed to the remote then the history will be lost, in which case it makes sense, but if you have pushed it, then there's no need to duplicate that history in 'master'.

Remotes never have feature branches, if they do they are only secondary remotes, not main ones.

 

So, yes, I want that history preserved. Rebase without fast forward does that. I usually don't commit experimental stuff in branches that will end up being merged. And if I do, then it is because such commits contain some approaches that are not applicable at the moment, but I want them preserved for the future because requirements can change or some missing compiler/framework features might be implemented. 

 

Sometimes, some cruft will end up in repo, but there is not enough of that to be a problem.

Share this post


Link to post
45 minutes ago, Fr0sT.Brutal said:

squash is just join all commits into one

Okay.  Yes, I can see that there's a git merge --squash command.

So I guess SourceTree squashes commits by default because when I merge and push I only get one new commit in the history of the target. The only reference to "squash" that I've come across in SourceTree is in the Interactive Rebase dialog (which I don't understand enough to dare use).

Share this post


Link to post
5 hours ago, Anders Melander said:

So I guess SourceTree squashes commits by default because when I merge and push I only get one new commit in the history of the target

IDK about SourceTree but it shouldn't. Merge adds single "merge commit" to your master branch but preserves all the history of a branch being merged.

For me squashing is good when I have tons of temporary WIP commits in feature branch and don't want to pollute history with them. Then, when a feature is done, I squash these commits into well-commented pretty commits that will go to master's history. Usually I do it with cherry-pick. When a branch is ready, I merge it (sometimes I intentionally force merge even if changes could be fast-forwarded just to designate that a feature has been implemented.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×