0

There are 5 commits that contain a new experimental feature, yet it makes master too slow, reason still unknown. How can I stash the newer commits or create a branch for them like ExpA so they do not mess up with the master branch?

Separate dir idea

Gererate from

...--o--o--A--B--C--D--E   <-- master

the following repos to separate dirs A, B, C, D and E in that order:

...--o--o--A   <-- master

...--o--o--A--B   <-- master

...--o--o--A--B--C   <-- master

...--o--o--A--B--C--D   <-- master

...--o--o--A--B--C--D--E   <-- master

but it is also possible to reformulate the goal in terms of branches so instead of creating separate dirs, create new branches A, B, C, D and E so it is easy to run the tester.m file just by changing branch.

Separate branch idea

     ---- A   <-- A
     |
     |------ A--B   <-- B
     ||
     || --- A--B--C   <-- C
     || |
     || |  A--B--C--D   <-- D
     \\ | /
      \\|/
...--o--o   
         \
          A--B--C--D--E   <-- master

How would test each commit and why? With some of the above ideas?

Suggest also other ideas if you have them! There may be some GUI program where having cursor above commit and pressing some key runs the stage -- this kind of feature would btw be supercool in Tig.

aynber
  • 22,380
  • 8
  • 50
  • 63
hhh
  • 50,788
  • 62
  • 179
  • 282
  • Without creating any new branches or repositories: Just do `git checkout A` and run your test; then do `git checkout B` and run your test, etc. — You can check out any commit into a detached HEAD to run your tests on the version of that commit. – poke Jan 24 '14 at 14:34
  • Sounds like what you really want here is [`git bisect master A~`](https://www.kernel.org/pub/software/scm/git/docs/git-bisect.html). – Greg Bacon Jan 24 '14 at 17:23
  • @GregBacon what is the A~? Is it a commit hash? Like git bisect 6f99fb970ddfcac4cd0bd8385b4f788f214e1df9~ ...cannot understand yet the git bisect: http://stackoverflow.com/questions/4713088/how-to-use-git-bisect. Is it for me if I don't want to get rid of the commits? I would like to make the A-B-C-D-E into an experimental feature. Ofc I need to first find the point A that can be the tricky part, bisect for finding it? – hhh Jan 25 '14 at 17:21
  • @hhh Yes, using the SHA like that will work. It means the parent of A, the last known good commit. Bisecting pinpoints the commit that caused a problem using the fewest, *O(log n)*, probes. – Greg Bacon Jan 25 '14 at 17:29
  • @GregBacon look I would like to do this: git bisect bad (go one commit backward), git bisect bad 3 (go 3 commits backward) and then I found the good commit -- this is the next master start where I want to move the bad commits to an experimental feature branch. Before marking bad, I need to do some fast test with ./tester.m file to check whether things work manually. Wolf explains doing the branch, http://stackoverflow.com/a/21334690/164148, but now I just need to find the correct point. How to do this process? – hhh Jan 25 '14 at 17:40

3 Answers3

1

Let's say your master branch looks like this:

    --A--B--C--D--E--F--G (master)

C, D, E, F, and G are the commits that you no longer want on master. So your goal is to make them be a branch, and have master reset to B. Therefor,

(0) git checkout master

(1) git branch experimental G

(2) git reset --hard B

That will leave you with:

    --A--B (master)
          \
           C--D--E--F--G (experimental)

Now you can build master without the experimental commits; and on the experimental branch, you can build everything.

Wolf
  • 4,254
  • 1
  • 21
  • 30
  • Haven't tested this but I think this solves one thing: moving the experimental commits to new branch, +1 for it. Now I need to find how to find that bad commit, apparently with `git bisect`. – hhh Jan 25 '14 at 17:54
0

Perhaps, source Freenode's Git channel.

git checkout -b <newbranchname> 'master@{2014-01-11 22:35}'
hhh
  • 50,788
  • 62
  • 179
  • 282
0

What you need to know here is that a "structural branch" (I'm experimenting with this term now) is formed by the commit graph, while a git branch label is merely "pasted onto" a commit (or "points to" a single commit, if you prefer that terminology).

It sounds like you have something like this right now:

...--o--o--A--B--C--D--E   <-- master

where A through E are the five commits that are this new experimental feature, and the earlier os are other commits. (Note that "time moves forward" left-to-right, i.e., the last o commit happened before A, and A happened before B, and so on.)

Let's draw the above with a kink in the line, which does not change it in any way, but makes room in the drawing for us to stick a second label on it. Then, let's stick a second label on it.

...--o--o   <-- new-label
         \
          A--B--C--D--E   <-- master

See how, if we could just swap those two labels, we'd have exactly what you asked for: master would point to the last commit just before A, and new-label would point to commit E which then "branches off master".

We can do exactly that. There's only one caveat: if anyone else is sharing this repository, either directly or (more commonly) via push and pull operations, the other people only expect branch labels to "move forward": to have new commits added over time, not to have commits "taken away" by going "back in time".

If they've picked up both your new commits (A through E) and the action of "moving the branch label master forward" from the last o commit up to E, and then you decide to "move the label backward", you must somehow tell them: "hey, guys, sorry, but I had to move the label backward in time". Then they may have to take more actions on their own to recover from this.

If nobody else has the commits yet, you're in great shape. If others might have them but are not using them, or are OK with taking actions to recover from "moving backward", then you're still in good shape.

Here's one shortest-way to achieve the trick with the labels (there are a few more equally short ways):

  1. Add a new label pointing to commit E:

    git checkout master  # if you're not already "on branch master"
    git checkout -b ExpA
    

    (this method has the advantage of leaving you "on branch ExpA", which I assume you'd like to be).

  2. Now that there's a second label on E, forcibly move master back five commits:

    git branch -f master master~5
    

    (master~5 means "move back 5 commits from where master is now; you can use any other method to name the desired commit, which is the last o node in the drawings above; master@{date} as in your own answer can do the trick, for instance).

  3. Only if you've already pushed commits A through E to some central repository (here, I assume it's called origin) on branch master. Note that this step is at least slightly dangerous (sometimes more than slightly, if others have pushed more commits onto master over there) and should not be done until everyone else knows about this and has agreed to it (and if you don't know what you're doing here, let someone else—someone who's in charge of the central repository origin—do it instead):

    git push -f origin master
    

If others have your commits and you are not allowed to "go back in time" with the labels, you'll need to "revert" stuff instead; see other StackOverflow discussions about this.

torek
  • 448,244
  • 59
  • 642
  • 775
  • Is `label` a git term? Sorry I am somehow misguided by the the start such as `structural branch`. Firstly, I need to find out the start of `'real master'`. Then I need to move the all commits before that to experimental branch. Perhaps the second point `git bracnh -f master master~5` does it? Does it move the five first commits to new bracnh by force? But what is the name of the experimental branch? – hhh Jan 25 '14 at 18:00
  • "Label" is a [general English-language word](http://dictionary.reference.com/browse/label) that I am using in its noun sense. This covers git branch names, git tag names, and special references like `stash` (used by `git stash`). For most of the post I'm using it more specifically to refer to a git branch *name*, not to be confused with the data structure formed by following parent commit-IDs in a series of commits, which git *also* calls "a branch". I'm afraid we may have some language barrier issues here, aside from git's own problem of using one word ("branch") for two different ideas. – torek Jan 25 '14 at 19:12