[FFmpeg-devel] [Ffmpeg-devel] SVN dump

Andy Parkins andyparkins
Wed May 2 15:57:12 CEST 2007


On Wednesday 2007 May 02, Michael Niedermayer wrote:

Apologies in advance for the length of this message; I'm trying to be 
thorough, but it's probably all a bit boring.

> because of that we need to be able to fix mistakes and sending everyone a
> mail saying "hg strip 1234deadbeef" is not an option. thats even more
> primitive than cvs

I'm curious - what is the procedure now to undo a commit in subversion?

 * -- * -- * -- * -- B -- * -- * -- *

How do you get rid of B without damaging the subsequent commits?

I ask only because whatever procedure you use with subversion would probably 
work with git.

While it is generally considered bad form to undo commits that have been 
pushed to other developers, it doesn't actually "break" anything, as in - 
it's not the end of the world - the repository isn't corrupted.  People will 
get a bit mixed up for a while, but everything that can be done can be 
undone.

The reason revision editing is a problem is that every commit is dependendent 
on all the previous commits; so while you _can_ remove a commit and replace 
the subsequent commits, you get a situation like this:

 * -- * -- * -- * -- B -- 1 -- 2 -- 3
                 \
                  1' -- 2' -- 3'

Then, people who grabbed 1, 2 or 3 will be basing their new revisions off of 
them, rather than off of the replacements 1', 2', or 3'.  When they try to 
send those updates to the central repository they'll get error messages about 
not being able to update a non-fast-forward reference.

For a central repository, you would probably set the configuration such that 
non-fast-forwards are not allowed.  So, what is a fast-forward?

Let's say we have a central repository with a branch, master, on it.

  1 --- 2 --- 3 (master)           CENTRAL REPO

I track that upstream branch in my repository with a tracking branch, let's 
call it "up/master".  Then I want to do some work on it, so I create my own 
working branch called "mymaster", initially pointing at the same commit 
as "up/master"

  1 --- 2 --- 3 (up/master)        DEVELOPER REPO
                (mymaster)

I make a few commits to my repository, which moves mymaster as I go:

  1 --- 2 --- 3 (up/master)        DEVELOPER REPO
               \
                4 -- 5 (mymaster)
  
Now, I want to push those changes back to central.  I tell git to push the 
local branch mymaster to the remote branch master.  Step 1 is that the new 
commits are uploaded:

 1 --- 2 --- 3 (master)            CENTRAL REPO
              \
               4 -- 5

Step 2 is that the branch reference is updated to point at the new branch tip:

 1 --- 2 --- 3 -- 4 -- 5 (master)   CENTRAL REPO

That was a fast forward - master was moved from 3 to 5 - in git parlance 
revision 3 is a subset of revision 5 - and hence is a fast-forward update. 

Now imagine this, instead of committing on top of the existing revisions, I 
rewind my branch pointer and start committing on an earlier revision:

  1 --- 2 --- 3 (up/master)        DEVELOPER REPO
         \
          4 -- 5 (mymaster)

Try to push this.  Step 1, send the commits:

 1 --- 2 --- 3 (master)            CENTRAL REPO
        \
         4 -- 5

Step 2, update master to point at the new tip... ERROR - the old tip, 3, is 
not a subset of the new tip, 5; "master" would have to be rewound to an 
earlier commit to perform this update.  Git prevents this - damage would be 
prevented.  Note that the same is true even if no new commits were added: 
rewinding an existing branch during a push is prevented by default.

However, it is possible to force an update to the repository and overrule that 
protection if you really, really want to.  In that case though, if people 
have independently started building on the old revision, then you will get 
screams because the fast-forward protection will stop them from pushing their 
changes; however they can easily fetch the updated upstream branch and rebase 
their changes to that new branch tip and it will all start working again.  
It's more a matter of etiquette than technology :-)

----

To finish the above story, under normal circumstances this is probably a merge 
situation:

  1 --- 2 ------- 3 (up/master)        DEVELOPER REPO
         \         \
          4 -- 5 -- 6 (mymaster)

Now 6 is a merge commit, and now 3 could be fast-forwarded to 6.  
Alternatively, if the developer didn't want to treat this as a merge, they 
could rebase their changes onto the 3 revision, and the central repository 
would let the update happen.



Andy
-- 
Dr Andy Parkins, M Eng (hons), MIET
andyparkins at gmail.com




More information about the ffmpeg-devel mailing list