adentinger
adentinger

Reputation: 1404

Pushing up to commit with --set-upstream?

Let's take this case I'm having right now:

$ git log --decorate
commit A (HEAD -> dev)
commit B
commit C
commit D
commit E
commit F (origin/dev)

Now, if I want to push up to HEAD, since I've already done --set-upstream, I can just git push.

In my case, I want to push on dev, but only up to commit C, since I often amend/squash/rephrase the latest few commits I have. I can do git push origin C:dev, but isn't there a less verbose way of doing that, given that I've set the dev branch to track origin/dev? I.e., is there a way for me not to have to specify the remote and the branch, but still push up to a certain commit?

Upvotes: 0

Views: 362

Answers (1)

torek
torek

Reputation: 488463

I can do git push origin C:dev, but isn't there a less verbose way of doing that ...

Not exactly less verbose, but perhaps easier.1 I assume that for C you mean the hash ID of commit C. There's also something else you can do. Depending on how you like to work, you might find this better, or not. See the section below the footnote.

When using the syntax git push remote refspec like this, with a refspec argument that contains a literal colon : character, the thing on the left side of the refspec argument can be anything that selects the desired commit. A raw hash ID works well, but so does a relative name like HEAD~2 or dev~2, and you can abbreviate the full hash ID to as short as four characters as long as this uniquely identifies the object.

The complete list of all possible ways to name any given commit are listed in the gitrevisions documentation.


1This depends on what you find easy, and how you count "verbose". A raw hash ID is 40 characters and dev~2 is 5, so obviously dev~2 is shorter, but in a way it's more verbose: it has three words in it, dev, ~, and 2. Counting can be tricky as well, when you have a few solid commits you wish to push along with a few dozen or hundred wobbly ones you want to avoid pushing yet—cut and paste of the raw hash ID may work better here.


A different, maybe better, workflow

The problem here arises because you're working on a branch you have named dev, which is kind of generic. Suppose instead you had a branch named wobbly-feature-xyz or perhaps wip/xyz, where wip stands for work in progress and is a signal to everyone in your group that this branch is going to have its history rewritten regularly and commits within it should not be depended-upon. Then you could safely save the in-progress, wobbly commits in the other Git at origin (which perhaps is more reliable and gets regular backups and so on), knowing that no one will depend on them the way they are likely to depend on commits in dev.

This lets you use git rebase -i to edit the history of your wobbly branch as much as you like. When you have some commits within that wobbly branch that you feel are solid and should go into dev, you can put them there.

Let's say we start out with this repository in your Git and the Git at origin and, well, pretty much everyone else:

...--A--B--C   <-- master
         \
          D--E   <-- dev
              \
               G--H--I   <-- wip/xyz

You now work on your feature branch wip/xyz while others work on their wip feature branches. Alice decides some commit(s) are done and ready to go and gets them into dev so after you run git fetch origin, your repository now has:

...--A--B--C   <-- master, origin/master
         \
          D--E   <-- dev
             |\
             | F   <-- origin/dev
             \
              G--H--I   <-- wip/xyz, origin/wip/xyz

You can now fast-forward your dev to pick up the new commit, more or less at any time:

...--A--B--C   <-- master, origin/master
         \
          D--E--F   <-- dev, origin/dev
              \
               G--H--I   <-- wip/xyz, origin/wip/xyz

and then, at any time as well, use git rebase to copy your three WIP commits:

      ...         G'-H'-I'  <-- wip/xyz
         \       /
          D--E--F   <-- dev, origin/dev
              \
               G--H--I   <-- origin/wip/xyz

and then force-push since everyone has agreed that this sort of thing happens:

     ...--D--E--F   <-- dev, origin/dev
                 \
                  G'-H'-I'  <-- wip/xyz, origin/wip/xyz

If you now feel that the first of your three commits is quite solid, you can now git checkout your own dev and fast-forward-merge that commit into it:

     ...--D--E--F   <-- origin/dev
                 \
                  G'  <-- dev
                   \
                    H'-I'  <-- wip/xyz, origin/wip/xyz

Now you can git push while on dev to push commit G', giving:

     ...--D--E--F--G'  <-- dev, origin/dev
                    \
                     H'-I'  <-- wip/xyz, origin/wip/xyz

Except for the fact that you are now permitted (but not obligated) to push your work-in-progress commits, this has the exact same effect, as far as all other Git repositories go, as what you're doing now. The key difference is that the label dev in your repository moves forward under your control at more specific times, so that you never have "wobbly" commits on your own dev.

(This may, or may not, make it easier for you to keep track of which commits you think are solid.)

Upvotes: 1

Related Questions