How to delete content in Azure DevOps wiki

Today I got a simple but interesting question about Azure DevOps, how can I completely delete the content of the wiki? There are not so many reason for this, but sometimes you really want to start from scratch. Now suppose you have your wiki:

image

Figure 1: Wiki with a simple page

You have created some pages, you played a little bit with the wiki, you attached some cute pets photo and content to the wiki itself, maybe just to gain familiarity with the wiki itself.

image

Figure 2: Wiki with some content on it.

Now you want to delete everything, such as that no member of the team should be able to retrieve pages and content anymore.

Azure DevOps Wiki are nothing more than a Git Repository with MarkDown content, so you can directly manipulate git repository if you need to alter wiki history

To do a low level manipulation of the wiki, you should simply clone wiki repository locally, you can simply find repository url in the UI

image

Figure 3: Clone wiki repository from the ui.

That menu option simply lets you to grab url of the repository, then you can simply clone the repository locally and verify all the commits done in the wiki. (I use command line but you can use any UI of you choiche)

image

Figure 4: Content of the wiki, a simple git repository

Now if you look a Figure 4 you can notice that the wiki is nothing more than a git repository with a commit for each modification you did to the wiki. Now, if you really want to reset everything and start wiki from scratch, you can simply issue a

git reset --hard SHA_OF_FIRST_COMMIT

Where SHA_OF_FIRST_COMMIT is the address of the very first commit, the one with the comment Initializing wiki, in my example 86ec4c9. After the command was executed your local wikiMaster branch point to the very first commit of the repository, an empty wiki.

image

Figure 5: Your local wikiMaster branch was reset to the very first commit, now wikiMaster point to an empty wiki

Now you can simply push with –force option to reset remote branch to the very same commit.

git push --force

Open again wiki page to verify that now it reverted to the original version. Actually the server still has the previous commit in the database, but they are not reachable anymore and they will be deleted over time by internal garbage collection.

Resetting to the very first commit actually delete everything from the wiki, restoring it to its pristine content

This scenario is not really common, but a real common scenario is when you mistakenly write something in the wiki, save the page and then you want to delete what you have written. There are lots of reason for this requirement, you mistakenly inserted sensitive data like passwords or tokens, or you simply write something that you want to permanently delete.

If you look to Figure 4, suppose you simply paste a wrong image and you want to remove that image and all related content from the history of the page. If you simply edit the wiki page, remove the image, then save again the page, the data is still in the history, anyone can find again the content you want to remove. The only solution is to rewrite git history.

Since a Wiki is a git repository, everything you did remain in history of the page, if you included sensitive information, even if you edit the page, removed that information and save again is not enough.

From Figure 4 you can verify that the incriminated commit is 97e520e. If you followed my previous example you can simply reset everything to the previous commit, actually deleteing every content that was inserted after that commit.

git reset --hard 97e520e^

Special char ^ indicates first parent of a commit, so previous instruction tell git to reset to the commit parent of bad commit. After this operation a git push – force will reset the branch from the server. The incriminated content is now gone, along with every content that was inserted after. Actually you restored wiki content to a past point in time.

Git reset –hard in your wiki repository allows you to restore a Wiki on a point in time, but everything that happened after that moment will be lost.

This is not a perfect approach, suppose you realize that someone stored a password in the wiki some days ago, you do not want to lose everything but simply remove that specific content and leaving other commit unchanged. Thanks to git flexibility you can obtain this operation with an interactive rebase.

git rebase 97e520e^ -i

This will actually trigger a complete rewrite of the history from the parent of the incriminated commit to the last commit of the wiki. I’m not going to give you a complete explanation of an interactive rebase, but basically you are presented with the list of all commits, starting with the commit you want to delete to the latest commit in the branch.

image

Figure 6: Delete the commit with interactive rebase.

In Figure 6 you are seeing an example in which I have a single commit after the one you want to remove, but nothing changes if you have tons of commits after. You simply need to change the command for the first commit (the commit you want to delete) from pick to d (delete). Leave all other rows unchanged. Then simply save the script to continue (if you are not familiar with VIM simply press I to edit the file, change the file then press ESC to come back in command mode and press : then w then q then ENTER).

This command actually deletes only the commit you want to delete, leaving all following commits unchanged. You actually scissor knife removed a single bad save from your wiki.

image

Figure 7: Commit was removed, local branch has not anymore commit 97e520e

Now you should be 100% sure that no one else modified the wiki in the short timespan you need to clone and rebase the repository so you can issue a git push –force to overwrite content of the repo on AzDo instance.

A git interactive rebase is an operation where you are rewriting history, so you can selectively remove a single commit from the history.

This will actually preserve all content of the wiki, you only removed a single commit from the wiki. There is no more history of that commit inside the Wiki. (actually deleted commit is still unreachable on the server, but there is no way for other to retrieve it).

If you want to completely remove a page with all the history of that page, you need to delete multiple commits, but luckily git has a filter-branch or more advanced comment. You can find more detail here https://help.github.com/en/articles/removing-sensitive-data-from-a-repository

Have I ever told you how much I love Git? :)

Gian Maria.

Git and the Hell of case sensitiveness

If you know how git works, you are perfectly aware that, even if you work in operating systems with case insensitive file system, all commit are case sensitive. Sometimes if you change the case of a folder, then commit modification of files inside that folder, you will incur into problems, because if casing of the path changes, the files are different for the Git Engine (but not for operating systems like windows).

In the long run you will face some annoying problems, like git showing that some of the files are modified (while you didn’t touch them) and you are unable to undo changes or work with those files. This problem will become really annoying during rebase operations.

Having files with only case differences is one of the most annoying problem with Git Repositories in Windows

Luckily enough, Azure DevOps has an option for Git Repository where you can have the engine prevent commits that contains file names with only case differences, to avoid this problem entirely.

image

Figure 1: Options for Cross platform compatibility can solve most headaches

The first option completely blocks pushes that contains files not compatible across platform and is the option that we are looking for, because it will block you from pushing code that will lead to case sensitiveness problems.

The other two options are equally needed, because the second one will prevent you from pushing path with forbidden names or incompatible characters (remember that this is different between Windows and Linux). Finally the third one will block pushes that contains path with unsupported length, a problem that is really nasty for Windows Users.

In the end, if you have case sensitiveness problem in your repository and you already pushed your code, because you did not have these option enabled, I can suggest you a nice tool available in GitHub that find all problems in the repository and fix them, it is called Git Unite. You can clone the project, compile in visual studio then just launch from command line giving path of a local git repository as single arguments and it will do everything automatically.

Gian Maria

NullReferenceException in windows when Git fetch or pull

After updating Git to newer 2.19.1. for windows, it could happen that you are not able to use anymore credential manager. The sympthom is, whenever you git fetch or pull, you got a NullReferenceException and or error  unable to read askpass response from ‘C:/Program Files/Git/mingw64/libexec/git-core/git-gui—askpass’

Git credential manager for Windows in version 2.19.1 could have some problem and generates a NullReference Exception

Clearing Windows Credential Manager does not solves the problem, you still have the same error even if you clone again the repo in another folder. To fix this you can simply download and install the newest version of the Git Credential Manager for windows. You can find everything at this address.

image

Figure 1: Download page for release of Git Credential Manager for Windows

Just install the newest version and the problem should be solved.

Gian Maria

Configure Visual Studio 2017 15.5 for pull –rebase

I’m a great fan of rebasing over merge and I’m convinced that the default pull should be a fetch and rebase, using fetch and merge only when it is really needed. Not having the option to configure a GUI to do a pull –rebase is a really annoying problem, that can be somewhat limited configuring pull.rebase git option to true, as explained in previous post. Actually, the lack of rebase on pull option makes me stop using the IDE.

To have a linear history in Git, always consider rebase over merge, especially for everyday pulls.

I’ve used this technique extensively with VS 2017, the only drawback is an error during pull because VS complains about “unknown merge result” since he was not able to find merge commit. Give this, I was always reluctant to suggest to customers, because it is not good having your IDE constantly show error at each pull.

After updating to 15.5 version I noticed that the error went away and the IDE correctly tells me that a pull with a rebase occurred. If I open the global or repository settings in Team Explorer I can found that now, finally, pull.rebase is supported.

image

Figure 1: Pull with rebase is now supported, as well as other interesting options.

Actually these are the basic settings of Git, if you configure the repository or globally the Rebase local branch when pulling, it will set pull.rebase to true, nothing more. The important aspect is that the IDE now honor the settings. Suppose you have one local commit and one remote commit like in Figure 2:

image

Figure 2: Classic situation where you have local commit and remote commits

Now if you simply press the pull command in the IDE, you will see that VS is correctly issuing a rebase. When everything is finished you are informed that indeed a rebase was done, the error went away.

image

Figure 3: Visual  Studio correctly rebased local branch on the remote branch.

With this latest addition I can confirm that Visual Studio is now a really interesting IDE to work with Git (even if, if you are experienced with Git, probably you will still stick in CommandLine most of your time).

P.s: Another nice addition is the support to prune after fetch and support to push –force. If you try to push a commit after an amend, instead of the standard error, you will be prompted with a  MessageBox that asks you if you really want to force the push.

image

Figure 4: MessageBox asking for a push force if needed.

If you are curious about why VS is using a –force-with-lease instead of a standard –force, please read this article. Basically it is a way to force the push if no one had pushed something else in the meanwhile. If you really need to force a push, like when you rebase a feature branch, you can always use commandline.

Gian Maria.

Configure Git repository for automatic pull –rebase

I’m not a great fan of Git Graphical User Interfaces, I use mainly command line, but I needed to admit that, for novice user, the ability to use a GUI is something that can easy the pain of transition to a new tool. Visual Studio 2017 is a decent GUI for Git and since .NET developers are used to it, people want to stay as much as possible inside the IDE, leaving the commandline only for special operation (squash, reflog, etc)

The main problem I found with VS 2017 is the “pull” button, because I’m a great fan of pull –rebase instead that normal pull, because the history will be clearer. Suppose you have this situation:

image

Figure 1: Situation before a pull, one local commit, one remote commit

This is a standard, a developer has created a local commit and we have another commit done in the origin/master branch. This is what the develop see in Visual Studio sync interface:

image

Figure 2: The same situation of Figure 1 as seen in Visual Studio

From the comment you can see that the incoming commit is a simple add of readme.md file , this is unrelated to the modification done by developer, but if he press the pull button here is the result.

image

Figure 3: A merge commit is created due to the pull operation

If everyone will use the default pull option, the team will create a lot of unnecessary merge commits, thus I really prefer the pull –rebase approach, but the problem is: in Visual Studio there is no easy way to issue a pull –rebase and the pull button is just to easy to press to convince people to go to command line and issue a pull –rebase. Luckily there is an option that you can configure globally and that will default pull operation to do a rebase instead that a merge

git config –global pull.rebase true

After this configuration was done, whenever you issue a git pull, the –rebase option will be added automatically for you. Since VS 2017 honors git settings, if you press the pull button you got the right behavior, even if it is complaining that the merge result was unknown. (a rebase happened, not a merge)

image

Figure 4: After the pull, VS is complaining because the merge result is unknown, because a rebase was instead done

image

Figure 5: Indeed GitViz confirm that the pull operation was a pull –rebase

You can just ignore the error in Visual Studio and accept the fact that now, whenever you press the Pull button in Visual Studio you will trigger a pull with a rebase instead that a pull with merge.

This technique is not going to work with older version of Visual Studio, because they used the LibGit2Sharp library.

Gian Maria.